Подтвердить что ты не робот

Самый простой способ сделать lua script wait/pause/sleep/block в течение нескольких секунд?

Я не могу понять, как заставить lua делать какие-либо общие трюки, например

  • sleep - остановить все действия в потоке

  • pause/wait - не переходите к следующему , но разрешить другой код в приложение для продолжения

  • block - не переходите к следующей команде, пока текущий возвращает

И я читал, что

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

потребляет процессорное время.

Любые предложения? Есть ли API-запрос, который мне не хватает?

ОБНОВЛЕНИЕ. Я давно задал этот вопрос, пытаясь заставить WOW Lua переиграть действия по расписанию (т.е. стоять, подождать 1 сек, танцевать, подождать 2 секунды, сидеть без пауз, они происходят почти все за ту же четверть секунды.) Как оказалось, WOW намеренно отключил почти все, что позволяет делать действия на часах, потому что это может сломать игру или включить ботов. Я решил пересоздать часы, как только он был убран, мне нужно было бы сделать что-то сумасшедшее, как создать рабочий массив (с действием и временем выполнения), а затем зарегистрировать обработчик событий на кучу общих события, такие как перемещение мыши, затем в четном обработчике обрабатывают любое действие, время которого наступило. Обработчик событий фактически не будет выполняться каждые X миллисекунд, но если это происходит каждые 2-100 мс, это будет достаточно близко. К сожалению, я никогда не пробовал.

4b9b3361

Ответ 1

Это не легче. Сон может быть реализован в вашем FLTK или что-то еще, но это охватывает все лучшие способы выполнения стандартных типов системных спящих без особых прерываний событий. Вот:

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

Ответ 2

[Я собирался опубликовать это как комментарий к сообщению John Cromartie, но не понял, что вы не можете использовать форматирование в комментарии.]

Я согласен. Отбрасывание его в оболочку с помощью os.execute() определенно будет работать, но в общем случае вызовы оболочки дорого. Обтекание некоторых C-кода будет намного быстрее во время выполнения. В C/С++ в системе Linux вы можете использовать:

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;
}

Затем, в основном, do:

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

где "L" - ваш lua_State. Затем в вашей Lua script, вызванной из C/С++, вы можете использовать свою функцию, вызывая:

sleep(1000) -- Sleeps for one second

Ответ 3

Если вы используете LuaSocket в своем проекте или просто установите его и не против использовать его, вы можете используйте функцию socket.sleep(time), которая спит в течение заданного промежутка времени (в секундах).

Это работает как в Windows, так и в Unix, и вам не нужно компилировать дополнительные модули.

Я должен добавить, что функция поддерживает дробные секунды в качестве параметра, т.е. socket.sleep(0.5) будет спать полсекунды. Он использует Sleep() в Windows и nanosleep() в другом месте, поэтому у вас могут быть проблемы с точностью Windows, когда time становится слишком низким.

Ответ 4

Вы не можете сделать это в чистом Lua без питания CPU, но там есть простой, не переносимый способ:

os.execute( "sleep 1" )

(он будет заблокирован)

Очевидно, что это работает только в операционных системах, для которых "sleep 1" является допустимой командой, например Unix, но не Windows.

Ответ 5

для окон вы можете это сделать:

os.execute("CHOICE /n /d:y /c:yn /t:5")

Ответ 6

Функция сна - Использование: sleep(1) -- sleeps for 1 second

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

Функция паузы - Использование: pause() -- pause and waits for the Return key

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

надеюсь, это то, что вам нужно!: D - Joe DF

Ответ 7

Я бы выполнил простую функцию, чтобы обернуть функцию ожидания хост-системы в C.

Ответ 8

Pure Lua использует только то, что находится в стандарте ANSI C. Luiz Figuereido модуль lposix содержит большую часть того, что вам нужно для создания более системных вещей.

Ответ 9

Для второго запроса пауза/ожидание, когда вы прекращаете обработку в 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)

Ответ 10

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')

Ответ 11

Я согласен с Джоном в том, что он обертывает функцию сна. Вы также можете использовать эту завернутую функцию сна для реализации функции паузы в lua (которая просто будет спать, а затем проверяет, изменилось ли какое-либо условие так часто). Альтернативой является использование крючков.

Я не совсем уверен, что вы имеете в виду с вашей третьей точкой маркера (обычно команды не выполняются до того, как будет выполнен следующий?), но крючки могут также помочь в этом.

См: Вопрос: Как я могу закончить поток Lua? для примера использования крючков.

Ответ 12

Вы можете использовать:

os.execute("sleep 1") -- I think you can do every command of CMD using os.execute("command")

или вы можете использовать:

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

wait(YourNumberHere)

Ответ 13

Вы хотите win.Sleep(milliseconds), methinks.

Да, вы определенно не хотите делать оживленный, как вы описываете.

Ответ 14

Также легко использовать Alien в качестве оболочки libc/msvcrt:

> luarocks install alien

Затем из 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: Я не пробовал это на MSWindows; Я даже не знаю, имеет ли msvcrt функцию usleep()

Ответ 15

Я начал с Lua, но потом обнаружил, что хочу увидеть результаты вместо простой старой командной строки. Поэтому я просто добавил следующую строку в свой файл и, вернее, стандарт:

please press any key to continue...

os.execute("PAUSE")

Мой примерный файл - это только печать, а затем запись с паузой, поэтому я уверен, что вам не нужно это размещать здесь.

Я не уверен, что последствия процессора для запуска процесса для полного script. Тем не менее, может оказаться полезным остановить остановку кода в процессе отладки.

Ответ 16

Я считаю, что для окон вы можете использовать: os.execute("ping 1.1.1.1 /n 1 /w <time in milliseconds> >nul как простой таймер. (удалите "< > " при вставке времени в миллисекундах) (между остальной частью кода и >nul) есть пробел

Ответ 17

Это должно работать:

    os.execute("PAUSE")

Ответ 18

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