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

我无法弄清楚如何让 lua 进行任何常见的时间处理技巧,比如:

  • sleep - 停止线程的所有操作

  • pause/wait - 不要进入下一个命令,但允许应用程序中的其他代码继续

  • block - 在当前命令返回之前不要执行下一个命令

我读到一个

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

会消耗 CPU 时间。

有什么建议吗?我是否错过了 API 调用?

更新:我很久以前写了这个问题,试图让 WOW Lua 按照时间表重放动作(例如站立,等待 1 秒钟,跳舞,等待 2 秒钟,坐下。如果没有暂停,这些动作几乎在同一个季度内发生。)事实证明,WOW 故意禁用了几乎所有允许按时钟执行操作的功能,因为这可能会破坏游戏或启用机器人。 我想重新创建一个时钟,一旦它被拿走,我就不得不做一些疯狂的事情,比如创建一个工作数组(带有动作和执行时间),然后在许多常见的事件上注册事件处理程序,比如鼠标移动,然后在事件处理程序中处理任何时间到来的操作。事件处理程序实际上不会每 X 毫秒发生一次,但如果每 2-100 毫秒发生一次,就足够接近了。不幸的是,我从来没有尝试过。

原文链接 https://stackoverflow.com/questions/1034334

点赞
stackoverflow用户47529
stackoverflow用户47529

你需要使用 win.Sleep(milliseconds),我想这样更好。

是的,你一定不想像你描述的那样进行忙等待。

2009-06-23 18:39:08
stackoverflow用户56243
stackoverflow用户56243

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

2009-06-23 18:46:00
stackoverflow用户70365
stackoverflow用户70365

我同意 John 对于包装 sleep 函数的看法。

你可以使用这个经过包装的 sleep 函数来实现在 lua 中的暂停函数(它会简单地睡眠然后不断检查某个条件是否发生改变)。另外一个选择是使用钩子。

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

参考: 问题:如何干净地结束 Lua 线程? 这里有一个使用钩子的例子。

2009-06-23 21:09:02
stackoverflow用户41661
stackoverflow用户41661

纯 Lua 只使用 ANSI 标准 C 中的内容。Luiz Figuereidolposix 模块包含了大部分你需要进行更多系统级操作的东西。

2009-06-25 21:38:36
stackoverflow用户18403
stackoverflow用户18403

你不能在纯 Lua 中做到而不消耗 CPU,但有一种简单的、非可移植的方法:

os.execute("sleep 1")

(它将阻塞)

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

2009-06-25 21:44:51
stackoverflow用户109549
stackoverflow用户109549

[我本来想在 John Cromartie 的帖子中留言,但没有意识到在评论中无法使用格式。]

我同意。使用 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;
}

然后,在主函数中,执行:

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

其中 "L" 是您的 lua_State。然后,在从 C/C++ 中调用的 Lua 脚本中,可以通过调用以下方式使用您的函数:

sleep(1000) -- 睡眠 1 秒钟
2009-07-07 15:25:59
stackoverflow用户596285
stackoverflow用户596285

对于第二个请求,暂停/等待,即在 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)
2011-06-25 14:58:04
stackoverflow用户1021239
stackoverflow用户1021239

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

> luarocks install alien

然后在 Lua 中使用:

require 'alien'

if alien.platform == "windows" then
    -- 未经测试!!
    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)  -- 睡眠 500 毫秒
print('world')

注意事项:我没有在 MSWindows 上尝试过这个方法;我甚至不知道 msvcrt 是否有一个 usleep() 函数。

2011-10-31 00:38:10
stackoverflow用户221509
stackoverflow用户221509

如果你的项目中使用了 LuaSocket,或者你已经安装了它并愿意使用它,你可以使用 socket.sleep(time) 函数来睡眠一定的时间(以秒为单位)。

该函数在 Windows 和 Unix 上均可使用,无需编译其他模块。

需要注意的是,该函数支持以小数秒为参数,即 socket.sleep(0.5) 可以使程序睡眠半秒钟。它在 Windows 上使用 Sleep(),在其他地方使用 nanosleep()。因此,当 time 值过低时,你可能会遇到 Windows 精度问题。

2011-10-31 08:32:16
stackoverflow用户1165448
stackoverflow用户1165448

对于Windows,你可以这样做:

os.execute("CHOICE /n /d:y /c:yn /t:5")
2012-01-23 17:13:58
stackoverflow用户883015
stackoverflow用户883015

睡眠函数 - 用法:sleep(1) -- 睡眠1秒

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

暂停函数 - 用法:pause() -- 暂停并等待回车键

function pause()
   io.stdin:read'*l'
end

希望这是您需要的!:D - Joe DF

2012-11-07 04:24:39
stackoverflow用户1900477
stackoverflow用户1900477
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)  -- 睡眠 500 毫秒
print('world')
2012-12-13 09:38:58
stackoverflow用户2522046
stackoverflow用户2522046

我最开始用的是 Lua,但后来我发现我想要看到结果,而不只是命令行闪烁。所以我只需在我的文件中添加以下行,即可看到标准的结果:

请按任意键继续...

os.execute("PAUSE")

我的示例文件只包含打印和暂停语句,所以我相信你不需要在这里发布那些内容。

我不确定对于运行整个脚本而言,CPU的影响有多大。但是,在调试中中途停止代码可能会很有用。

2013-06-25 23:15:33
stackoverflow用户2360556
stackoverflow用户2360556

我相信对于 Windows 操作系统,你可以使用以下代码作为简单的计时器:os.execute("ping 1.1.1.1 /n 1 /w <time in milliseconds> >nul。(在插入毫秒数时,请删除尖括号 < >)(代码的其余部分和 >nul 之间有一个空格)

2013-07-04 16:59:28
stackoverflow用户3150187
stackoverflow用户3150187

你可以使用:

os.execute("sleep 1") -- 我认为你可以使用 os.execute("command") 来执行 CMD 的每个命令

或者你可以使用:

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

wait(你的毫秒数)
2014-01-17 15:36:00
stackoverflow用户3393301
stackoverflow用户3393301

这应该可以工作:

    os.execute("PAUSE")
2014-03-07 15:29:52
stackoverflow用户3500476
stackoverflow用户3500476
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
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
2014-04-05 06:07:00
stackoverflow用户3707001
stackoverflow用户3707001

不再简单了。可能会在你的 FLTK 或其他地方实现睡眠,但这涵盖了所有最佳方法来执行标准的系统睡眠而不需要特殊事件中断。看:

-- 我们使用 "pcall"(尝试/捕获) "ex",它最好包括 os.sleep
-- 这可能是将来 Lua 版本的标准库的一部分(超过 5.2)
local ok, ex = pcall(require"ex")
if ok then
   -- print("Ex")
   --我们现在也需要黑客? ex.install(),
   pcall(ex.install)
   --让我们尝试别的。为什么不呢?
   if ex.sleep and not os.sleep then os.sleep = ex.sleep end
end

if not os.sleep then
   --我们制作 os.sleep
   --首先通过尝试 ffi,这是 LuaJIT 的一部分,它允许我们编写 C 代码
   local ok, ffi = pcall(require"ffi")
   if ok then
      -- print("FFI")
      --我们可以使用 FFI
      --让我们再次检查一下,确保我们仍然没有 os.sleep
      if not os.sleep then
         --好的,这是我们的自定义 C 睡眠代码:
         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
      --如果我们无法使用 FFI,则尝试使用 LuaSocket,它只称为 "socket"
      --我有 99.99999999% 的把握
      local ok, socket = pcall(require"socket")
      -- ...但我不确定这一点
      if not ok then local ok,socket = pcall(require,"luasocket") end
      --所以,如果我们真的在使用套接字...
      if ok then
         -- print("Socket")
         --我们也可以确认没有 os.sleep
         if not os.sleep then
            --我们的自定义 socket.select to os.sleep 代码:
            os.sleep = function (sec)
               socket.select(nil, nil, sec)
            end
         end
      else
         --现在我们将测试 "alien"
         local ok, alien = pcall(require"alien")
         if ok then
         -- print("Alien")
         --升船...
            if not os.sleep then
               --如果我们还没有 os.sleep,那就是
               --现在,我不知道以下代码做了什么
               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(nil0,sec * 1000)
                  end
               end
            end
         elseif package.config:match("^\\") then
            -- print("busywait")
            --如果计算机反对 NIXon,我们就忙碌等待
            --然后摇晃它
            os.sleep = function (sec)
               local timr = os.time()
               repeat until os.time ()> timr + sec
            end
         else
            -- print("NIX")
            --或者我们被 NIXed
            os.sleep = function (sec)
               os.execute("sleep " .. sec)
            end
         end
      end
   end
end
2014-06-04 12:26:11
stackoverflow用户88888888
stackoverflow用户88888888

你可以这样做:

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!")
2020-02-25 17:00:13
stackoverflow用户17338535
stackoverflow用户17338535

你可以尝试这个:

function wait(seconds)
    local start = os.time()
    repeat until os.time() > start + seconds
end
wait(5) print("货物。什么货物?货物,储存。") -- 等待 5 秒,然后打印

我在 Lua CLI 中尝试过,可以运行。

2022-01-24 01:49:29