3

コルーチン(Lua)を使用してイベントを処理する方法を理解しようとしています。これを行う一般的な方法は、現在のコルーチンを生成し、待機していることが発生したときにそれを再開するラッパー関数を作成することであるように思われます。それは良い解決策のように思えますが、これらの問題はどうですか?:

  1. 同時に複数のイベントを待ち、どちらが先に来るかに応じて分岐するにはどうすればよいですか?または、そのような状況を回避するためにプログラムを再設計する必要がありますか?

  2. 一定期間後に待機をキャンセルするにはどうすればよいですか?イベントループは、ソケットの送信/受信ラッパーにタイムアウトパラメータを含めることができますが、カスタムイベントについてはどうでしょうか。

  3. コルーチンをトリガーして、外部から状態を変更するにはどうすればよいですか?たとえば、呼び出されたときにコルーチンを別のステップにジャンプさせたり、別のイベントの待機を開始したりする関数が必要です。

編集:

現在、コルーチンをイベントに登録するシステムがあり、イベントが発生するたびに、イベント名と情報をパラメーターとしてコルーチンが再開されます。このシステムでは、1と2は問題ではなく、3は、コロに別のステップにジャンプする特別なイベント名を期待させ、その名前を引数として再開することで解決できます。また、カスタムオブジェクトには、同じ方法でイベントハンドラーを登録するメソッドを含めることができます。

これがイベント処理にコルーチンを使用する正しい方法と考えられているのではないかと思います。たとえば、読み取りイベントとタイマーイベント(読み取りのタイムアウトとして)があり、読み取りイベントが最初に発生した場合、手動でタイマーをキャンセルする必要があります。これは、コルーチンを使用したシーケンシャルな性質やイベントの処理に適合していないようです。

4

1 に答える 1

4

同時に複数のイベントを待ち、どちらが先に来るかに応じて分岐するにはどうすればよいですか?

登録するLua関数だけでなく、コルーチンを使用する必要がある場合(たとえば、処理を実行し、イベントを待機してからさらに処理を実行する関数がある場合)、これは非常に簡単です。コルーチンが再開されたときにcoroutine.yield渡されたすべての値を返します。coroutine.resume

したがって、イベントを渡すだけで、それが待機しているかどうかをスクリプトが自動的に判断できるようになります。実際、これを行うための単純な関数を作成できます。

function WaitForEvents(...)
  local events = {...}
  assert(#... ~= 0, "You must pass at least one parameter")

  do
    RegisterForAnyEvent(coroutine.running()) --Registers the coroutine with the system, so that it will be resumed when an event is fired.
    local event = coroutine.yield()
    for i, testEvt in ipairs(events) do
      if(event == testEvt) then
        return
      end
    end
  until(false)
end

この関数は、指定されたイベントの1つが発生するまで生成され続けます。ループはそれが一時的なものであると想定し、RegisterForAnyEvent1つのイベントに対してのみ関数を登録するため、イベントが発生するたびに再登録する必要があります。

一定期間後に待機をキャンセルするにはどうすればよいですか?

上記のループにカウンターを置き、一定時間後に離れます。読者の練習問題として残しておきます。それはすべて、アプリケーションが時間を測定する方法によって異なります。

コルーチンをトリガーして、外部から状態を変更するにはどうすればよいですか?

Lua関数を別の「状態」に魔法することはできません。関数を呼び出して結果を返すことしかできません。したがって、あるプロセス内でスキップしたい場合は、スキップできるようにLua関数システムを作成する必要があります。

それをどのように行うかはあなた次第です。待機していないコマンドの各セットを個別のLua関数にすることができます。または、待機状態を設計して先にスキップできるようにすることもできます。または何でも。

于 2012-07-24T01:34:22.737 に答える