最简单的方法让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
我会在C中实现一个简单的函数来包装主机系统的睡眠功能。
我同意 John 对于包装 sleep 函数的看法。
你可以使用这个经过包装的 sleep 函数来实现在 lua 中的暂停函数(它会简单地睡眠然后不断检查某个条件是否发生改变)。另外一个选择是使用钩子。
我不太确定你在第三个要点中的意思是什么(命令通常不是在执行下一个之前就已经完成了吗?),但是钩子也可以帮助解决这个问题。
参考: 问题:如何干净地结束 Lua 线程? 这里有一个使用钩子的例子。
纯 Lua 只使用 ANSI 标准 C 中的内容。Luiz Figuereido 的lposix 模块包含了大部分你需要进行更多系统级操作的东西。
你不能在纯 Lua 中做到而不消耗 CPU,但有一种简单的、非可移植的方法:
os.execute("sleep 1")
(它将阻塞)
显然,这只适用于那些“sleep 1”是有效命令的操作系统,例如 Unix,但不适用于 Windows。
[我本来想在 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 秒钟
对于第二个请求,暂停/等待,即在 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)
函数。使用 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() 函数。
如果你的项目中使用了 LuaSocket,或者你已经安装了它并愿意使用它,你可以使用 socket.sleep(time)
函数来睡眠一定的时间(以秒为单位)。
该函数在 Windows 和 Unix 上均可使用,无需编译其他模块。
需要注意的是,该函数支持以小数秒为参数,即 socket.sleep(0.5)
可以使程序睡眠半秒钟。它在 Windows 上使用 Sleep()
,在其他地方使用 nanosleep()
。因此,当 time
值过低时,你可能会遇到 Windows 精度问题。
对于Windows,你可以这样做:
os.execute("CHOICE /n /d:y /c:yn /t:5")
睡眠函数 - 用法: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
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')
我最开始用的是 Lua,但后来我发现我想要看到结果,而不只是命令行闪烁。所以我只需在我的文件中添加以下行,即可看到标准的结果:
请按任意键继续...
os.execute("PAUSE")
我的示例文件只包含打印和暂停语句,所以我相信你不需要在这里发布那些内容。
我不确定对于运行整个脚本而言,CPU的影响有多大。但是,在调试中中途停止代码可能会很有用。
我相信对于 Windows 操作系统,你可以使用以下代码作为简单的计时器:os.execute("ping 1.1.1.1 /n 1 /w <time in milliseconds> >nul
。(在插入毫秒数时,请删除尖括号 < >)(代码的其余部分和 >nul
之间有一个空格)
你可以使用:
os.execute("sleep 1") -- 我认为你可以使用 os.execute("command") 来执行 CMD 的每个命令
或者你可以使用:
function wait(waitTime)
timer = os.time()
repeat until os.time() > timer + waitTime
end
wait(你的毫秒数)
这应该可以工作:
os.execute("PAUSE")
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
不再简单了。可能会在你的 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(nil,0,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
你可以这样做:
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!")
你可以尝试这个:
function wait(seconds)
local start = os.time()
repeat until os.time() > start + seconds
end
wait(5) print("货物。什么货物?货物,储存。") -- 等待 5 秒,然后打印
我在 Lua CLI 中尝试过,可以运行。
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
- 如何创建一个 lua 脚本以针对特定键为 fluentbit 进行限流
你需要使用
win.Sleep(milliseconds)
,我想这样更好。是的,你一定不想像你描述的那样进行忙等待。