Easiest way to make lua script wait/pause/sleep/block for a few seconds?
我不知道如何使lua进行任何常见的计时技巧,例如
-
sleep-停止对线程
的所有操作
-
暂停/等待-不要继续下一个
命令,但允许在
申请继续 -
block-在输入以下内容之前,不要继续执行下一个命令
当前一个返回值
我已经读过一个
1 2 3 | while os.clock()<time_point do --nothing end |
耗尽CPU时间。
有什么建议吗?我是否缺少API调用?
更新:很久以前,我写了这个问题,试图让WOW Lua按计划重播动作(例如,站立,等待1秒,跳舞,等待2秒,坐着。在没有暂停的情况下,这些动作几乎都在同一时间发生事实证明,WOW故意禁用了所有允许按时执行操作的操作,因为它可能会破坏游戏或启用机器人。我想重新创建一个时钟后,就不得不做一些疯狂的事情,例如创建一个工作数组(带有动作和执行时间),然后在一系列常见事件上注册一个事件处理程序,例如鼠标移动,然后在偶数处理程序中处理时间已到的任何操作。事件处理程序实际上不会每隔X毫秒发生一次,但是如果每2到100毫秒发生一次,则它足够接近。可悲的是我从未尝试过。
[我打算将其发布为对John Cromartie的帖子的评论,但没有意识到您不能在评论中使用格式。]
我同意。使用os.execute()将其放到shell中肯定可以,但是总的来说,进行shell调用很昂贵。在运行时package一些C代码会更快。在Linux系统上的C / C中,可以使用:
1 2 3 4 5 6 7 8 9 | 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; } |
然后主要执行:
1 2 | lua_pushcfunction(L, lua_sleep); lua_setglobal(L,"sleep"); |
其中" L"是您的lua_State。然后,在从C / C调用的Lua脚本中,可以通过调用以下命令来使用您的函数:
1 | sleep(1000) -- Sleeps for one second |
如果您碰巧在项目中使用LuaSocket,或者只是安装了它而又不介意使用它,则可以使用
这在Windows和Unix上均有效,并且您不必编译其他模块。
我应该补充一点,该函数支持小数秒作为参数,即
您不能在不消耗CPU的情况下使用纯Lua进行操作,但是有一种简单,不可移植的方式:
os.execute(" sleep 1")
(它将阻止)
显然,这仅适用于" sleep 1"是有效命令的操作系统,例如Unix,但不适用于Windows。
睡眠功能-用法:
1 2 3 4 5 6 | local clock = os.clock function sleep(n) -- seconds local t0 = clock() while clock() - t0 <= n do end end |
暂停功能-用法:
1 2 3 | function pause() io.stdin:read'*l' end |
希望,这就是您所需要的! :D-乔DF
对于Windows,您可以执行以下操作:
1 | os.execute("CHOICE /n /d:y /c:yn /t:5") |
没有比这容易的事情了。睡眠可以在您的FLTK或任何其他方式中实现,但这涵盖了进行标准类型的系统睡眠的所有最佳方法,而无需特殊事件中断。看哪:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | -- 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 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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') |
对于第二个请求,暂停/等待,如果您停止在Lua中的处理并继续运行您的应用程序,则需要协同程序。您最终得到一些如下的C代码:
1 2 3 4 5 | Lthread=lua_newthread(L); luaL_loadfile(Lthread, file); while ((status=lua_resume(Lthread, 0) == LUA_YIELD) { /* do some C code here */ } |
在Lua中,您具有以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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) |
Pure Lua仅使用ANSI标准C中的内容。Luiz Figuereido的lposix模块包含许多您需要做的系统工作。
我将实现一个简单的函数,将主机系统的sleep函数package在C中。
您可以使用:
1 | os.execute("sleep 1") -- I think you can do every command of CMD using os.execute("command") |
或者您可以使用:
1 2 3 4 5 6 | function wait(waitTime) timer = os.time() repeat until os.time() > timer + waitTime end wait(YourNumberHere) |
我同意约翰package睡眠功能。
您还可以使用此package的睡眠函数在lua中实现暂停功能(该函数将简单地睡眠,然后检查某个条件是否经常改变了)。另一种方法是使用钩子。
我不确定您的第三个要点是什么意思(命令通常不会在执行下一个命令之前完成吗?),但是钩子也可以帮助解决这个问题。
请参阅:
问题:我怎样才能干净地结束Lua线程?
有关使用钩子的示例。
我相信对于Windows,您可以使用:
(插入时间(以毫秒为单位时,删除" <>"))(其余代码和
我从Lua开始,但是后来我发现我想查看结果,而不仅仅是旧的命令行刷新。因此,我只是将以下行添加到我的文件中,嘿,请记住,标准:
1 2 3 | please press any key to continue... os.execute("PAUSE") |
我的示例文件只是打印文件,然后是暂停声明,因此我确定您不需要在此处发布文件。
我不确定为完整脚本运行进程对CPU的影响。但是,在调试中停止代码中间流可能很有用。
您想要
是的,您绝对不想像您描述的那样进行繁忙的等待。
将Alien用作libc / msvcrtpackage器也很容易:
1 | > luarocks install alien |
然后来自lua:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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') |
注意事项:我没有在MSWindows上尝试过;我什至不知道msvcrt是否具有usleep()
您可以执行以下操作:
1 2 3 4 5 6 7 8 | 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!") |
这应该起作用:
1 | os.execute("PAUSE") |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 |