休眠函数

lua-users home
wiki

一个常见的需求是让程序暂停(休眠)一定时间,最好不要使用忙等待。

在 ANSI C 中没有这样的函数,因此在标准 Lua 中也不存在。但是,有一些扩展库和对外部程序的调用可以做到这一点。

解决方案:忙等待

local clock = os.clock
function sleep(n)  -- seconds
  local t0 = clock()
  while clock() - t0 <= n do end
end
-- warning: clock can eventually wrap around for sufficiently large n
-- (whose value is platform dependent).  Even for n == 1, clock() - t0
-- might become negative on the second that clock wraps.

解决方案:C 扩展

扩展提案 中有一个休眠函数。它可能调用 Win32 Sleep 或 POSIX usleep。这里有一个 [usleep/sleep C 包装器] 示例。

LuaApr 绑定有一个 [apr.sleep()] 函数,它在 Windows 和 UNIX 上工作,并支持亚秒级分辨率。

lalarm 库 [1] 可以在 POSIX 上设置闹钟。

winapi(仅限 Windows)有一个 [sleep] 函数。 [github]

如果 FFI 接口(Alien 或 c/invoke - 绑定代码到 Lua)可用,您可以调用您拥有的任何操作系统函数。

解决方案:sleep 命令

function sleep(n)
  os.execute("sleep " .. tonumber(n))
end

Windows 没有这样的内置命令。但是,Windows Server Resource Kit 中有一个 sleep。Cygwin 和 MinGW 中也有 sleep。此外,Windows 7 中还提供“timeout”实用程序。

  os.execute("timeout " .. tonumber(n)) -- specific to win7 (and probably higher) 

解决方案:ping 或其他程序

function sleep(n)
  if n > 0 then os.execute("ping -n " .. tonumber(n+1) .. " localhost > NUL") end
end
-- version 20100715 - fixed off-by-one second

这主要针对 Windows,在没有 sleep 命令的情况下。存在其他变体,例如 "perl -e 'sleep(" .. tonumber(n) .. ")'""php -r sleep(" .. tonumber(n) .. ");"

解决方案:I/O 等待

io.stdin:read'*l'

这不是休眠,但在类似情况下可能有用。它等待用户按下 Enter 键。

解决方案:使用 WScript(Windows)

function sleep(n)
  local vb = "test.vbs"
  local f = assert(io.open(vb,"w"))
  f:write("WScript.Sleep(" .. (tonumber(n) * 1000) .. ")\n")
  f:close()
  os.execute(vb)
end

参见 [2]

解决方案:sleep()

POSIX sleep() 调用提供整数秒休眠。

require "posix"

posix.sleep(3)

解决方案:socket.sleep()

LuaSocket ? 模块提供了一个休眠函数。

socket = require("socket")

function sleep(sec)
    socket.sleep(sec)
end

sleep(0.2)

解决方案:ngx.sleep()

Nginx Lua 模块提供了一个休眠函数。可以指定时间分辨率,最高可达 0.001 秒(即 1 毫秒)。在幕后,此方法使用 Nginx 定时器。

ngx.sleep(sec)

解决方案:lsocket.select()

如果您能忍受套接字库的依赖关系,select() 超时提供了一个相当便携的亚秒级睡眠。

local lsocket  = require("lsocket")

function sleep(sec)
    lsocket.select(sec)
end

sleep(2)

解决方案:LuaJIT FFI/LuaFFI

local ffi = require "ffi"
ffi.cdef "unsigned int sleep(unsigned int seconds);"
ffi.C.sleep(2)

解决方案:os.time()

function sleep(s)
  local ntime = os.time() + s
  repeat until os.time() > ntime
end

解决方案:os.clock()

. .

使用 os.clock() 方法而不是 os.time(),您可以将精度提高到百分之一秒,而 os.time() 只能允许基于时间戳的间隔,在执行时可以是 0.1 到 1 秒之间的任何值。os.time() 方法非常适合超过 2 秒的较长时间段,在这些时间段内精度不是那么重要。

function sleep(s)
  local ntime = os.clock() + s/10
  repeat until os.clock() > ntime
end

另请参阅


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2019 年 10 月 20 日下午 2:12 GMT (差异)