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


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,或者只是安装了它而又不介意使用它,则可以使用socket.sleep(time)函数,该函数可以hibernate给定的时间(以秒为单位)。 >

这在Windows和Unix上均有效,并且您不必编译其他模块。

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


您不能在不消耗CPU的情况下使用纯Lua进行操作,但是有一种简单,不可移植的方式:

os.execute(" sleep 1")

(它将阻止)

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


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

1
2
3
4
5
6
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

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,您可以使用:os.execute("ping 1.1.1.1 /n 1 /w <time in milliseconds> >nul作为一个简单的计时器。
(插入时间(以毫秒为单位时,删除" <>"))(其余代码和>nul之间有一个空格)


我从Lua开始,但是后来我发现我想查看结果,而不仅仅是旧的命令行刷新。因此,我只是将以下行添加到我的文件中,嘿,请记住,标准:

1
2
3
please press any key to continue...

os.execute("PAUSE")

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

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


您想要win.Sleep(milliseconds),方法。

是的,您绝对不想像您描述的那样进行繁忙的等待。


将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