maneira mais fácil de fazer lua roteiro de espera / pause / sleep / bloco por alguns segundos?
-
06-07-2019 - |
Pergunta
Eu não consigo descobrir como obter lua para fazer todos os truques de tempo comuns, tais como
-
sono - parar toda a ação em linha
-
pause / espera - não ir para a próxima comando, mas permitir que outro código na aplicativo para continuar
-
bloco - não ir para o próximo comando até que a se retorna atuais
E eu li que um
while os.clock()<time_point do
--nothing
end
consome tempo de CPU.
Todas as sugestões? Existe uma chamada de API que estou perdendo?
Atualizar :. Eu escrevi esta questão há muito tempo tentando obter WOW Lua para repetir ações em uma programação (ou seja, ficar, esperar 1 seg, dança, espere 2 segundos, sentar-se sem pausas, estes acontecem quase todos no mesmo quarto de segundo.) Como se viu WOW tinha propositadamente desativada praticamente tudo o que permite fazer a ação em um relógio, porque poderia quebrar o jogo ou permitir bots. eu percebi a re-criar um relógio, uma vez que tinha sido tirado, eu teria que fazer algo louco como criar uma matriz de trabalho (com um tempo de ação e execução) e em seguida, registrar um manipulador de eventos em um monte de eventos comuns, como movimento do mouse, em seguida, no manipulador mesmo, processar qualquer ação cujo tempo chegou. O manipulador de eventos não iria realmente acontecer a cada X milisegundos, mas se estivesse acontecendo a cada 2-100 ms, seria perto o suficiente. Infelizmente eu nunca tentei.
Solução
Ele não fica mais fácil do que isso. O sono pode ser implementado em sua FLTK ou qualquer outra coisa, mas esta abrange todas as melhores maneiras de fazer tipo padrão dos sonos do sistema sem interrupções de eventos especiais. Eis:
-- 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
Outras dicas
[Eu ia postar isso como um comentário sobre pós de John Cromartie, mas não sabia que você não poderia usar a formatação em um comentário.]
Eu concordo. Soltando-a um shell com os.execute () vai certamente funcionar, mas em chamadas gerais shell fazer é caro. Envolvendo algum código C será muito mais rápido em tempo de execução. Em C / C ++ em um sistema Linux, você pode usar:
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;
}
Então, em principal, fazer:
lua_pushcfunction(L, lua_sleep);
lua_setglobal(L, "sleep");
onde "L" é o seu lua_State. Então, em seu script Lua chamado de C / C ++, você pode usar a função chamando:
sleep(1000) -- Sleeps for one second
Se acontecer de você usar LuaSocket em seu projeto, ou apenas tê-lo instalado e não se importa de usá-lo, você pode usar o socket.sleep(time)
função que acomoda para uma determinada quantidade de tempo (em segundos).
Isso funciona tanto em Windows e Unix, e você não tem que compilar módulos adicionais.
Gostaria de acrescentar que a função suporta frações de segundo como um parâmetro, ou seja socket.sleep(0.5)
vai dormir meio segundo. Ele usa Sleep()
em Windows e nanosleep()
em outro lugar, então você pode ter problemas com a precisão do Windows quando time
fica muito baixo.
Você não pode fazê-lo em puro Lua sem comer CPU, mas há uma maneira simples, não-portáteis:
os.execute ( "sleep 1")
(ele irá bloquear)
Obviamente, isso só funciona em sistemas operacionais para os quais "sleep 1" é um comando válido, por exemplo Unix, mas não no Windows.
para janelas que você pode fazer isso:
os.execute("CHOICE /n /d:y /c:yn /t:5")
Função do sono - Uso: sleep(1) -- sleeps for 1 second
local clock = os.clock
function sleep(n) -- seconds
local t0 = clock()
while clock() - t0 <= n do
end
end
Função Pausa - Uso: pause() -- pause and waits for the Return key
function pause()
io.stdin:read'*l'
end
esperança, este é o que você precisava! : D - Joe DF
Gostaria de implementar uma função simples para embrulhar função de suspensão do sistema host em C.
Pure Lua usa apenas o que está no padrão ANSI C. Luiz de Figueiredo lposix módulo contém muito do que você precisa fazer as coisas mais systemsy.
Para a solicitação de segunda, pause / espera, onde você parar de processar em Lua e continuar a executar o aplicativo, você precisa coroutines. Você acaba com algum código C como esta a seguir:
Lthread=lua_newthread(L);
luaL_loadfile(Lthread, file);
while ((status=lua_resume(Lthread, 0) == LUA_YIELD) {
/* do some C code here */
}
e na Lua, você tem o seguinte:
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)
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')
Eu concordo com John on envolvendo a função dormir. Você também pode usar esta função dormir envolto para implementar uma função de pausa na lua (que simplesmente iria dormir, em seguida, verificar para ver se uma determinada condição mudou de vez em quando). Uma alternativa é a utilização ganchos.
Eu não sei exatamente o que você quer dizer com o seu terceiro bulletpoint (não comanda normalmente completa antes do próximo é executado?), Mas ganchos pode ser capaz de ajudar com isso também.
Veja: Pergunta: Como posso terminar uma linha Lua limpa ? para um exemplo de utilização de ganchos.
Você pode usar:
os.execute("sleep 1") -- I think you can do every command of CMD using os.execute("command")
ou você pode usar:
function wait(waitTime)
timer = os.time()
repeat until os.time() > timer + waitTime
end
wait(YourNumberHere)
Você quer win.Sleep(milliseconds)
, methinks.
Sim, você definitivamente não quer fazer uma movimentada-wait como você descreve.
É também fácil de usar estrangeiro como um libc / msvcrt fardos:
> luarocks install alien
Depois de 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')
Caveat lector: Eu não tentei isso em MSWindows; Eu não sei mesmo se msvcrt tem uma usleep ()
Eu comecei com Lua, mas, em seguida, eu descobri que eu queria ver os resultados em vez de apenas o flash bom linha de comando de idade. Então, eu apenas adicionei a seguinte linha para o meu arquivo e voilá, o padrão:
please press any key to continue...
os.execute("PAUSE")
Meu exemplo do arquivo é apenas uma impressão e, em seguida, uma indicação de pausa, por isso estou certo de que você não precisa que postou aqui.
Eu não tenho certeza sobre as implicações da CPU de um executando um processo para um script completo. No entanto parando no meio do fluxo de código na depuração poderia ser útil.
Eu acredito que para o Windows que você pode usar: os.execute("ping 1.1.1.1 /n 1 /w <time in milliseconds> >nul
como um temporizador simples.
(Remover o "<>" ao inserir o tempo em milissegundos) (há um espaço entre o resto do código e >nul
)
Isso deve funcionar:
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