web-dev-qa-db-ja.com

luaスクリプトを数秒間待機/一時停止/スリープ/ブロックさせる最も簡単な方法は?

次のような一般的なタイミングトリックを実行するためにluaを取得する方法がわかりません。

  • スリープ-スレッド上のすべてのアクションを停止します

  • 一時停止/待機-次のコマンドには進まないが、アプリケーション内の他のコードの続行を許可する

  • ブロック-現在のコマンドが戻るまで次のコマンドに進まない

そして、私はそれを読んだ

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

cPU時間を使い果たします。

助言がありますか?欠落しているAPI呼び出しはありますか?

[〜#〜] update [〜#〜]:ずっと前に、WOW Luaにスケジュールに従ってアクションを再生させるためにこの質問を書きました(つまり、立って、1秒待って、ダンスして、2秒待って、座ってください。休止なしで、これらはほぼすべて同じ四分の一秒で起こります。) ゲームを壊したり、ボットを有効にしたりする可能性があるため、時計を操作します。 時計を取り除いたら、時計を再作成することを考えました。アクションと実行時間)、マウスムーブなどの一般的なイベントのイベントハンドラーを登録し、イベントが発生したアクションを偶数ハンドラーで処理します。イベントハンドラは実際にはXミリ秒ごとに発生するわけではありませんが、2〜100ミリ秒ごとに発生する場合は十分に近いでしょう。悲しいことに私はそれを試したことがない。

30
MatthewMartin

これより簡単になることはありません。スリープは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'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
4
Fluff

[これを John Cromartie's postのコメントとして投稿するつもりでしたが、コメントでフォーマットを使用できないことに気づきませんでした。]

同意する。 os.execute()を使用してシェルにドロップすることは間違いなく機能しますが、一般的にシェル呼び出しを行うには費用がかかります。一部の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) -- Sleeps for one second
20
zslayton

プロジェクトで LuaSocket を使用する場合、または単にインストールして使用する気にしない場合は、 socket.sleep(time) 関数を使用できます。一定時間(秒単位)スリープします。

これはWindowsとUnixの両方で機能し、追加のモジュールをコンパイルする必要はありません。

関数がパラメーターとして小数秒をサポートすることを追加する必要があります。つまり、socket.sleep(0.5)は0.5秒スリープします。 Windowsでは Sleep() を使用し、他の場所では nanosleep() を使用するため、timeの場合はWindowsの精度に問題がある可能性があります低くなります。

18
Michal Kottman

CPUを消費せずに純粋なLuaでそれを行うことはできませんが、簡単で移植性のない方法があります。

os.execute( "sleep 1")

(ブロックします)

明らかに、これは「sleep 1」が有効なコマンドであるオペレーティングシステム、たとえばUnixでのみ機能しますが、Windowsでは機能しません。

10
Kknd

windowsの場合、これを行うことができます:

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

スリープ関数-使用法: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-ジョーDF

7
Joe DF

Pure LuaはANSI標準Cにあるもののみを使用します。LuizFiguereidoの lposix module は、より体系的なことを行うために必要なものの多くを含んでいます。

3
Norman Ramsey

ホストシステムのスリープ関数をCでラップする単純な関数を実装します。

3
John Cromartie
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')
3
avo

Luaで処理を停止し、アプリケーションの実行を続ける2番目のリクエストである一時停止/待機には、コルーチンが必要です。次のような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)
3
BMitch

次を使用できます。

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)
2
grmmhp

スリープ機能のラッピングについてジョンに同意します。このラップされたスリープ関数を使用して、luaに一時停止関数を実装することもできます(スリープしてから、特定の条件が頻繁に変更されるかどうかを確認します)。別の方法は、フックを使用することです。

3番目の箇条書きであなたが何を意味するのか正確にはわかりません(通常、コマンドは次のコマンドが実行される前に完了しないのですか?).

参照: 質問:どうすればLuaスレッドをきれいに終了できますか? フックの使用例について。

2
CiscoIPPhone

win.Sleep(milliseconds)、methinksが必要です。

ええ、あなたは間違いなくあなたが説明するような忙しい待ちをしたくありません。

1
chaos

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

警告:MSWindowsではこれを試していません。 msvcrtにusleep()があるかどうかさえわかりません

1
DSA

私はLuaから始めましたが、古き良きコマンドラインフラッシュだけではなく、結果を見たいと思いました。だから私はちょうど私のファイルに次の行を追加し、ちょっと標準、ちょっと:

please press any key to continue...

os.execute("PAUSE")

私のサンプルファイルは印刷物であり、一時停止の文ですので、ここに投稿する必要はないでしょう。

完全なスクリプトのプロセスを実行することのCPUの意味がわかりません。ただし、デバッグの途中でコードを停止すると便利です。

1
Ian

私はあなたが使用するかもしれない窓のために信じています:os.execute("ping 1.1.1.1 /n 1 /w <time in milliseconds> >nul簡単なタイマーとして。 (ミリ秒単位で時間を挿入するときに「<>」を削除します)(コードの残りと>nulの間にスペースがあります)

1
Cruz Jean
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
0
Descaii

これは動作するはずです:

    os.execute("PAUSE")
0
Anonymous