maneira mais fácil de fazer lua roteiro de espera / pause / sleep / bloco por alguns segundos?

StackOverflow https://stackoverflow.com/questions/1034334

  •  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.

Foi útil?

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top