0

2 つのイベント ハンドラーを持つコードがあります。これら 2 つのイベント ハンドラーが、実行すべき作業があることを別のメソッドに通知するようにします。

私は ManualResetEvent を使用してこれを実装しましたが、これが私が望むものを達成するための最良の方法であるかどうか、またはより良い方法があるかどうかはわかりません。

static ManualResetEvent autoEvent = new ManualResetEvent(false);

void begin() {
    ThreadPool.QueueUserWorkItem(new WaitCallback(genericHandler));
}

void OnEvent1(object sender) {
    autoEvent.Set();
}

void OnEvent2(object sender) {
    autoEvent.Set();
}

void genericHandler(object info) {
    while (true) {
        autoEvent.WaitOne();
        // do some work
    }
}

私が持っている最も重要な質問の 1 つは、次のとおりautoEvent.WaitOne()です。その間、別のイベントがトリガーSet()され、genericHandler がWaitOne()再び到達する前に呼び出されます。WaitOne に再び到達したとき、別の を待つか、またはに到達する前に a が呼び出されSet()た場合は続行しますか?Set()WaitOne()

これは、C# で複数のパブリッシャーと 1 つのサブスクライバー パターンを実装するための最良の方法ですか? または、ManualResetEvent の代わりに別のものを使用する必要がありますか?

注: Event1 と Event2 の優先度が異なるため、genericHandler は別のスレッドにあるため、ハンドラでは、Event2 を確認する前に、Event1 に保留中の作業があるかどうかを確認します。

4

2 に答える 2

0

質問とコードが漠然としているため、適切で具体的なアドバイスを提供できません。それは言った...

いいえ、ManualResetEventここでは の使用は適切ではありません。コードが不必要に複雑になるだけでなく、コードはスレッド プール (短時間のタスクのみを実行する必要がある) から取得した実行時間の長いスレッドに依存しています。

何らかの非同期作業の実行をトリガーするイベントが必要な場合は、Taskクラスを介して新しい作業単位が呼び出される async/await パターンを使用する必要があります。

例えば:

async void OnEvent1(object sender) {
    var workUnit = ... ; // something here that represents your unit of work
    await Task.Run(() => genericHandler(workUnit));
}

void OnEvent2(object sender) {
    var workUnit = ... ; // something here that represents your unit of work
    await Task.Run(() => genericHandler(workUnit));
}

void genericHandler(object info) {
    // do some work using info
}

イベント オブジェクトとbegin()メソッドが完全に削除されていることに注意してください。

各作業単位が互いに完全に独立しているかどうかは、あなたの質問からは明らかではありません。そうでない場合は、共有データを保護するために同期が必要になる場合もあります。繰り返しますが、より具体的な質問がなければ、これが何であるかを言うことはできませんが、lockステートメントまたはConcurrent...コレクションの 1 つを使用する可能性が最も高いでしょう。

于 2014-11-04T17:56:40.833 に答える
0

あなたのコードは実際にあなたが思っていることを実行し、あなたが説明する競合状態はまったく問題ではありません. MRE のドキュメントによると、設定されると、 への呼び出しによってリセットされるまで、「シグナル状態」のままになりWaitOneます。

于 2014-11-04T17:56:52.613 に答える