最简单的方法让lua脚本等待/暂停/睡眠/阻止几秒钟?

时间:2009-06-23 18:35:30

标签: lua

我无法弄清楚如何让lua做任何常见的计时技巧,例如

  • 睡眠 - 停止线程上的所有操作

  • 暂停/等待 - 不要继续下一步 命令,但允许其他代码 申请继续

  • 阻止 - 不要再继续下一个命令 当前的一个返回

我读过那个

while os.clock()<time_point do 
--nothing
end

耗尽CPU时间。

有什么建议吗?我缺少一个API调用吗?

更新:很久以前我写了这个问题试图让WOW Lua按计划重播动作(即站立,等待1秒,跳舞,等待2秒,坐下。没有停顿,几乎所有这些都发生在同一季度的第二季。)As it turned out WOW had purposely disabled pretty much everything that allows doing action on a clock because it could break the game or enable bots.我想要在它被带走后重新创建一个时钟,我必须做一些疯狂的事情,比如创建一个工作数组(带有动作和执行)然后在一堆常见事件上注册一个事件处理程序,比如鼠标移动,然后在偶数处理程序中,处理任何时间已到的动作。事件处理程序实际上不会每X毫秒发生一次,但如果它每隔2-100毫秒发生一次,它就足够接近了。可悲的是,我从未尝试过。

19 个答案:

答案 0 :(得分:20)

[我打算在John Cromartie's帖子上发表此评论,但没有意识到您无法在评论中使用格式。]

我同意。使用os.execute()将它删除到shell肯定会起作用,但通常使shell调用很昂贵。在运行时包装一些C代码会更快。在Linux系统上的C / C ++中,您可以使用:

static int lua_sleep(lua_State *L)
{
    int m = static_cast<int> (luaL_checknumber(L,1));
    usleep(m * 1000); 
    // usleep takes microseconds. This converts the parameter to milliseconds. 
    // Change this as necessary. 
    // Alternatively, use 'sleep()' to treat the parameter as whole seconds. 
    return 0;
}

然后,在main中,执行:

lua_pushcfunction(L, lua_sleep);
lua_setglobal(L, "sleep");

其中“L”是你的lua_State。然后,在从C / C ++调用的Lua脚本中,您可以通过调用:

来使用您的函数
sleep(1000) -- Sleeps for one second

答案 1 :(得分:18)

如果您碰巧在项目中使用了LuaSocket,或者只是安装了它并且不介意使用它,您可以使用socket.sleep(time)函数在预定的时间内休眠(在几秒钟内。

这适用于Windows和Unix,您无需编译其他模块。

我应该补充一点,该函数支持小数秒作为参数,即socket.sleep(0.5)将睡半秒。它在Windows上使用Sleep(),在其他地方使用nanosleep(),因此当time过低时,您可能会遇到Windows准确性问题。

答案 2 :(得分:10)

你不能在没有吃CPU的情况下在纯Lua中做到这一点,但是有一种简单的,不可移植的方式:

os.execute(“sleep 1”)

(它会阻止)

显然,这仅适用于“sleep 1”是有效命令的操作系统,例如Unix,而不是Windows。

答案 3 :(得分:8)

对于Windows,你可以这样做:

os.execute("CHOICE /n /d:y /c:yn /t:5")

答案 4 :(得分:7)

睡眠功能 - 用法:sleep(1) -- sleeps for 1 second

local clock = os.clock
function sleep(n)  -- seconds
   local t0 = clock()
   while clock() - t0 <= n do
   end
end

暂停功能 - 用法:pause() -- pause and waits for the Return key

function pause()
   io.stdin:read'*l'
end
希望,这就是你所需要的! :D - Joe DF

答案 5 :(得分:4)

它并不比这更容易。睡眠可能在你的FLTK或其他任何东西中实现,但这涵盖了在没有特殊事件中断的情况下进行标准排序系统睡眠的所有最佳方法。看哪:

-- we "pcall" (try/catch) the "ex", which had better include os.sleep
-- it may be a part of the standard library in future Lua versions (past 5.2)
local ok,ex = pcall(require,"ex")
if ok then
   -- print("Ex")
   -- we need a hack now too? ex.install(), you say? okay
   pcall(ex.install)
   -- let's try something else. why not?
   if ex.sleep and not os.sleep then os.sleep = ex.sleep end
end

if not os.sleep then
   -- we make os.sleep
   -- first by trying ffi, which is part of LuaJIT, which lets us write C code
   local ok,ffi = pcall(require,"ffi")
   if ok then
      -- print("FFI")
      -- we can use FFI
      -- let's just check one more time to make sure we still don't have os.sleep
      if not os.sleep then
         -- okay, here is our custom C sleep code:
         ffi.cdef[[
            void Sleep(int ms);
            int poll(struct pollfd *fds,unsigned long nfds,int timeout);
         ]]
         if ffi.os == "Windows" then
            os.sleep = function(sec)
               ffi.C.Sleep(sec*1000)
            end
         else
            os.sleep = function(sec)
               ffi.C.poll(nil,0,sec*1000)
            end
         end
      end
   else
      -- if we can't use FFI, we try LuaSocket, which is just called "socket"
      -- I'm 99.99999999% sure of that
      local ok,socket = pcall(require,"socket")
      -- ...but I'm not 100% sure of that
      if not ok then local ok,socket = pcall(require,"luasocket") end
      -- so if we're really using socket...
      if ok then
         -- print("Socket")
         -- we might as well confirm there still is no os.sleep
         if not os.sleep then
            -- our custom socket.select to os.sleep code:
            os.sleep = function(sec)
               socket.select(nil,nil,sec)
            end
         end
      else
         -- now we're going to test "alien"
         local ok,alien = pcall(require,"alien")
         if ok then
         -- print("Alien")
         -- beam me up...
            if not os.sleep then
               -- if we still don't have os.sleep, that is
               -- now, I don't know what the hell the following code does
               if alien.platform == "windows" then
                  kernel32 = alien.load("kernel32.dll")
                  local slep = kernel32.Sleep
                  slep:types{ret="void",abi="stdcall","uint"}
                  os.sleep = function(sec)
                     slep(sec*1000)
                  end
               else
                  local pol = alien.default.poll
                  pol:types('struct', 'unsigned long', 'int')
                  os.sleep = function(sec)
                     pol(nil,0,sec*1000)
                  end
               end
            end
         elseif package.config:match("^\\") then
            -- print("busywait")
            -- if the computer is politically opposed to NIXon, we do the busywait
            -- and shake it all about
            os.sleep = function(sec)
               local timr = os.time()
               repeat until os.time() > timr + sec
            end
         else
            -- print("NIX")
            -- or we get NIXed
            os.sleep = function(sec)
               os.execute("sleep " .. sec)
            end
         end
      end
   end
end

答案 6 :(得分:3)

我将实现一个简单的函数来将主机系统的睡眠函数包装在C中。

答案 7 :(得分:3)

require 'alien'

if alien.platform == "windows" then
  kernel32 = alien.load("kernel32.dll")
  sleep = kernel32.Sleep
  sleep:types{ret="void",abi="stdcall","uint"}
else
  -- untested !!!
  libc = alien.default
  local usleep = libc.usleep
  usleep:types('int', 'uint')
  sleep = function(ms)
    while ms > 1000 do
      usleep(1000)
      ms = ms - 1000
    end
    usleep(1000 * ms)
  end
end 

print('hello')
sleep(500)  -- sleep 500 ms
print('world')

答案 8 :(得分:3)

对于第二个请求,暂停/等待,在Lua中停止处理并继续运行您的应用程序,您需要协同程序。你最终得到了如下的一些C代码:

Lthread=lua_newthread(L);
luaL_loadfile(Lthread, file);
while ((status=lua_resume(Lthread, 0) == LUA_YIELD) {
  /* do some C code here */
}

在Lua中,您有以下内容:

function try_pause (func, param)
  local rc=func(param)
  while rc == false do
    coroutine.yield()
    rc=func(param)
  end
end

function is_data_ready (data)
  local rc=true
  -- check if data is ready, update rc to false if not ready
  return rc
end

try_pause(is_data_ready, data)

答案 9 :(得分:3)

Pure Lua仅使用ANSI标准C中的内容.Luiz Figuereido的lposix module包含了做更多系统事物所需的大部分内容。

答案 10 :(得分:2)

我赞同John关于睡眠功能的包装。 你也可以使用这个包装的睡眠函数在lua中实现一个暂停函数(它会简单地睡眠,然后检查某个条件是否经常发生变化)。另一种方法是使用钩子。

我不完全确定你的第三个要点是什么意思(在执行下一个命令之前通常不会完成命令吗?)但钩子也可以帮助解决这个问题。

请参阅: Question: How can I end a Lua thread cleanly? 有关使用挂钩的示例。

答案 11 :(得分:2)

您可以使用:

os.execute("sleep 1") -- I think you can do every command of CMD using os.execute("command")

或者您可以使用:

function wait(waitTime)
    timer = os.time()
    repeat until os.time() > timer + waitTime
end

wait(YourNumberHere)

答案 12 :(得分:1)

使用Alien作为libc / msvcrt包装器也很容易:

> luarocks install alien

然后来自lua:

require 'alien'

if alien.platform == "windows" then
    -- untested!!
    libc = alien.load("msvcrt.dll")
else
    libc = alien.default
end 

usleep = libc.usleep
usleep:types('int', 'uint')

function sleep(ms)
    while ms > 1000 do
        usleep(1000)
        ms = ms - 1000
    end
    usleep(1000 * ms)
end

print('hello')
sleep(500)  -- sleep 500 ms
print('world')

警告lector:我没有在MSWindows上尝试过这个;我甚至都不知道msvcrt是否有usleep()

答案 13 :(得分:1)

我从Lua开始,然后我发现我想要查看结果,而不仅仅是好的旧命令行flash。所以我只是将以下行添加到我的文件中,然后是标准:

please press any key to continue...

os.execute("PAUSE")

我的示例文件只是一个打印,然后是暂停声明,因此我确信您不需要在此处发布。

我不确定正在运行完整脚本的进程的CPU含义。但是,在调试中停止代码中间流程可能很有用。

答案 14 :(得分:1)

我相信你可以使用Windows os.execute("ping 1.1.1.1 /n 1 /w <time in milliseconds> >nul作为一个简单的计时器。 (以毫秒为单位插入时间时删除“&lt;&gt;”)(其余代码与>nul之间有空格)

答案 15 :(得分:1)

你想要win.Sleep(milliseconds),意思是。

是的,你绝对不想像你描述的那样忙碌等待。

答案 16 :(得分:0)

这应该有效:

    os.execute("PAUSE")

答案 17 :(得分:0)

cy = function()
    local T = os.time()
        coroutine.yield(coroutine.resume(coroutine.create(function()
    end)))
    return os.time()-T
end
sleep = function(time)
    if not time or time == 0 then 
        time = cy()
    end
    local t = 0
    repeat
        local T = os.time()
        coroutine.yield(coroutine.resume(coroutine.create(function() end)))
        t = t + (os.time()-T)
    until t >= time
end

答案 18 :(得分:0)

您可以这样做:

function Sleep(seconds)
    local endTime = os.time() + seconds
    while os.time() < endTime do
    end
end
print("This is printed first!")
Sleep(5)
print("This is printed 5 seconds later!")