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

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

  •  06-07-2019
  •  | 
  •  

質問

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

  • sleep-スレッドのすべてのアクションを停止

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

  • block-次のコマンドに進まないでください 現在のものが戻る

そして、私はそれを読みました

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

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

提案はありますか?欠落しているAPI呼び出しはありますか?

更新:ずっと前に、WOW Luaにスケジュールに従ってアクションを再生させようとしてこの質問を書きました(つまり、立ち、1秒待ち、ダンス、2秒待ち、座っています。これらはほぼすべて同じ四半期に発生します。) WOWは、ゲームを中断したりボットを有効にしたりする可能性があるため、クロックでアクションを実行できるほとんどすべてを意図的に無効にしました。取り去られたら時計を再作成します。作業配列を作成し(アクションと実行時間を含む)、マウスの移動などの一般的なイベントのイベントハンドラーを登録するなど、おかしなことをする必要があります。次に、偶数ハンドラーで、時間が来たアクションを処理します。イベントハンドラーは実際にはXミリ秒ごとに発生するわけではありませんが、2〜100ミリ秒ごとに発生する場合は十分に近いでしょう。悲しいことに、私はそれを試したことがない。

役に立ちましたか?

解決

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

他のヒント

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

同意します。 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");

where <!> quot; L <!> quot;あなたのlua_Stateです。次に、C / C ++から呼び出されたLuaスクリプトで、次を呼び出して関数を使用できます。

sleep(1000) -- Sleeps for one second

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

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

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

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

os.execute(&quot; sleep 1&quot;)

(ブロックします)

明らかに、これは「スリープ1」がサポートされているオペレーティングシステムでのみ機能します。 Unixなどの有効なコマンドですが、Windowsではありません。

これを行うことができるウィンドウの場合:

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

スリープ機能-使用法: sleep(1)-1秒間スリープします

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

一時停止関数-使用法: pause()-一時停止してReturnキーを待つ

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

希望、これがあなたが必要なものです! :D-ジョーDF

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

Pure LuaはANSI標準Cにあるもののみを使用します。LuizFiguereidoの lposixモジュールには、より体系的なことを行うために必要なものの多くが含まれています。

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

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

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

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

次を使用できます:

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)

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

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

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()があるかどうかもわかりません

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

please press any key to continue...

os.execute("PAUSE")

私のサンプルファイルは印刷物であり、一時停止の文ですので、ここに投稿する必要はありません。

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

使用できるウィンドウには os.execute(&quot; ping 1.1.1.1 / n 1 / w&lt; time in milliseconds&gt;&gt; nul を単純なタイマーとして使用します。 (ミリ秒単位で時間を挿入するときに&quot;&lt;&gt;&quot;を削除します)(コードの残りと&gt; nul の間にスペースがあります)

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

    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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top