9

ManualResetEvent を介してクロス プロセス イベントを作成しました。このイベントが発生すると、潜在的に n 個の異なるプロセスの n 個のスレッドのブロックが解除され、新しいデータを取得するために実行が開始されます。問題は、ManualResetEvent.Set の直後に Reset を実行しても、待機中のすべてのスレッドが起動しないように見えることです。ドキュメントはかなりあいまいです

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx

手動リセット イベント オブジェクトの状態がシグナル状態になると、ResetEvent 関数によって明示的に非シグナル状態にリセットされるまで、シグナル状態のままになります。オブジェクトの状態が通知されている間、任意の数の待機スレッド、または指定されたイベント オブジェクトの待機操作を後で開始するスレッドを解放できます。

PulseEventと呼ばれるメソッドがありますが、これはまさに私が必要としているものを実行しているように見えますが、残念ながらそれにも欠陥があります。

同期オブジェクトを待機しているスレッドは、カーネル モードの APC によって待機状態から一時的に削除され、APC の完了後に待機状態に戻る可能性があります。スレッドが待機状態から削除されている間に PulseEvent への呼び出しが発生した場合、PulseEvent は呼び出された時点で待機しているスレッドのみを解放するため、スレッドは解放されません。したがって、PulseEvent は信頼性が低く、新しいアプリケーションでは使用しないでください。代わりに、条件変数を使用してください。

現在、MS は条件変数の使用を推奨しています。

条件変数は、特定の条件が発生するまでスレッドが待機できるようにする同期プリミティブです。条件変数は、プロセス間で共有できないユーザー モード オブジェクトです。

docs に従っていると、確実に実行する運がなくなったようです。1 つの ManualResetEvent で規定された制限なしに同じことを達成する簡単な方法はありますか? または、サブスクライブされた呼び出し元ごとに ACK を取得するために、リスナープロセスごとに応答イベントを作成する必要がありますか? その場合、サブスクライブされたプロセスのpidを登録するために小さな共有メモリが必要になりますが、それはそれ自体の問題のセットをもたらすようです. 1 つのプロセスがクラッシュしたり、応答しない場合はどうなりますか? ....

いくつかのコンテキストを提供します。他のすべてのプロセスが共有メモリの場所から読み取る必要がある公開する新しい状態があります。一度に複数の更新が発生する場合、1 つの更新を見逃すことは問題ありませんが、プロセスは少なくとも最新の値を読み取る必要があります。タイムアウトでポーリングできましたが、それは正しい解決策ではないようです。

現在、私はダウンしています

ChangeEvent = new EventWaitHandle(false, EventResetMode.ManualReset, counterName + "_Event");

ChangeEvent.Set();
Thread.Sleep(1); // increase odds to release all waiters
ChangeEvent.Reset();
4

3 に答える 3