私は、複数のスレッドが待つことができるAutoResetEvent
のequivelantを望んでいます。設定された時点ですべてを再開したいと考えています。1つのイベントで複数のスレッドが待機していますか?
スレッドごとに1つずつ設定し、それぞれを設定することでこれが実現できることは分かっていますが、簡単な方法はありますか?イベントハンドルの配列に依存しない方法ですか?
(と思う)私がしたいが、これを行うことができるようにすることです効果的に何:
private volatile string state;
private MultiEventHandle stateChanged = new MultiEventHandle();
public void WaitForBlob()
{
while (true)
{
object saved = stateChanged.Current; // some sentinel value
if (state == "Blob") break;
stateChanged.WaitTilNot(saved); // wait til sentinel value != "current"
}
}
public void SetBlob()
{
state = "Blob";
stateChanged.Change(); // stateChanged.Current becomes a new sentinel object
}
すなわち、任意の数のスレッドがWaitForBlob
を呼び出すことはできませんし、いつでも(競合条件を)SetBlob
することができます待機中のすべてのスレッドがすぐに変更を検出します。重要なのは、スピンロックやThreading.Sleepsがないことです。
今私は "MultiEventHandle
"を比較的簡単に実装できると思います。しかし、私の質問は...良い方法があるのですか?確かに私はこれがかなり一般的な使用例でなければならないので、間違っているつもりですが、私は仕事のための内蔵ツールを見つけることができないようです。私はここで四角い車輪を発明しようとしているのではないかと恐れています。
実際の使用例では、ブロックするいくつかの機能があり、状態が自分の望むものになるのを待っています。 WaitForBlob、WaitForSusanなどがあります。私が望むのは、グローバルな状態が変わるたびに、待っているすべてのスレッドが状態を再評価して、今すぐ使えるかどうかを確認することです。私はManualResetEventsをどうやってそれを曲げることができたのか考えていません。 – Mania
詳細については、Eric LippertのC#での不変性のおかげで起こったものです。私は不変のAVLTreeのデータのヒープを格納している。時にはデバイスから読み込むのを待つときに、その一部が「ロック」されることがあります。今私はこの "ロックされた"セグメントを取得したい場合、最新の値を返す前に応答を待たなければなりません。だから私がする必要があるのは、ツリーが変更されるのを待つことです。その部分がまだロックされている場合は、ツリーがロックされていないときまで待機し続けます。複数のスレッドは、これをきれいに、できればスピンしない/小さなスリープなしで行うことができる必要があります。 – Mania
@Mania:もしあなたがAutoResetEventを使っているコードを持っていれば、ManualResetEventはまったく同じです。最初のスレッドが管理するときには、それ自体はリセットされません。考えられるもう1つのオプションは、イベントを使用することです。各イベントハンドラは、適切なスレッドがWait onと呼んだモニタにパルスを送ります。このような低レベルの概念を使用することは、いくつかの点で悪い考えであるように思えます... .NET 4を使用していますか?もしそうなら、TPLの何かが助けになるかもしれません。 –