【问题标题】:Easiest way to make lua script wait/pause/sleep/block for a few seconds?让lua脚本等待/暂停/睡眠/阻塞几秒钟的最简单方法?
【发布时间】:2010-11-05 06:45:11
【问题描述】:

我不知道如何让 lua 做任何常见的计时技巧,例如

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

  • 暂停/等待 - 不要继续下一个 命令,但允许在 申请继续

  • block - 不要继续下一个命令,直到 当前返回

我已经读过一个

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 毫秒发生一次,它就足够接近了。遗憾的是我从未尝试过。

【问题讨论】:

    标签: lua


    【解决方案1】:

    你想要win.Sleep(milliseconds),我想。

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

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

        见: Question: How can I end a Lua thread cleanly? 举个使用钩子的例子。

        【讨论】:

          【解决方案4】:

          Pure Lua 仅使用 ANSI 标准 C 中的内容。Luiz Figuereido 的 lposix module 包含您需要做更多系统性事情的大部分内容。

          【讨论】:

            【解决方案5】:

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

            os.execute("睡眠 1")

            (它会阻塞)

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

            【讨论】:

            • 请注意,在某些可以使用此功能的系统(例如 OS X)上,这不会导致 os.clock() 前进,因为不会消耗 CPU 时间。
            【解决方案6】:

            [我打算将此作为评论发布在 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
            

            【讨论】:

              【解决方案7】:

              对于第二个请求,暂停/等待,您在 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)
              

              【讨论】:

                【解决方案8】:

                使用 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')
                

                警告讲师:我没有在 MSWindows 上尝试过;我什至不知道 msvcrt 有没有 usleep()

                【讨论】:

                  【解决方案9】:

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

                  这适用于 Windows 和 Unix,您不必编译额外的模块。

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

                  【讨论】:

                    【解决方案10】:

                    对于 Windows,您可以这样做:

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

                    【讨论】:

                      【解决方案11】:

                      睡眠功能 - 用法: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 - 乔 DF

                      【讨论】:

                        【解决方案12】:
                        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')
                        

                        【讨论】:

                          【解决方案13】:

                          我从 Lua 开始,但后来我发现我想查看结果,而不仅仅是旧的命令行 flash。所以我只是在我的文件中添加了以下行,嘿,标准:

                          please press any key to continue...
                          
                          os.execute("PAUSE")
                          

                          我的示例文件只是一个打印,然后是一个暂停语句,所以我相信你不需要在这里发布。

                          我不确定为完整脚本运行进程对 CPU 的影响。但是,在调试过程中停止代码中间流可能会很有用。

                          【讨论】:

                            【解决方案14】:

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

                            【讨论】:

                              【解决方案15】:

                              你可以使用:

                              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)
                              

                              【讨论】:

                                【解决方案16】:

                                这应该可行:

                                    os.execute("PAUSE")
                                

                                【讨论】:

                                  【解决方案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
                                  

                                  【讨论】:

                                    【解决方案18】:

                                    没有比这更容易的了。睡眠可能会在您的 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
                                    

                                    【讨论】:

                                    • 在寻找简单的解决方案时,我越来越讨厌 lua ...
                                    【解决方案19】:

                                    你可以这样做:

                                    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!")
                                    

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 2018-11-16
                                      • 1970-01-01
                                      • 2010-11-13
                                      • 1970-01-01
                                      • 2014-04-05
                                      • 1970-01-01
                                      • 2016-09-03
                                      相关资源
                                      最近更新 更多