7

私がこれを行う場合:

private static System.Threading.AutoResetEvent event_2 = new System.Threading.AutoResetEvent(false);

そして、メインスレッドで私は:

event_2.Set();

状態をfalseからtrue?に変更します。

もしそうなら、それは基本的に行います:

AutoResetEventState = !AutoResetEventState 

?

4

5 に答える 5

4

他の回答に追加するには、これが必要な理由boolは次のとおりです (プロパティを単に切り替える代わりに)。

  1. Signalling: でブロックされたスレッドはe.WaitOne()signaledなり、そのうちの 1 つが続行されます。同期プリミティブを使用せずにこれを自分で行いたい場合は、何らかのポーリングを実装する必要があります。bool「ブロッキング」スレッドは、 (または、たとえばint)フィールドを定期的にポーリングして、フィールドが変更され、続行できるかどうかを確認する必要があります。他に何もないとしても、これは不必要に CPU サイクルを消費し、遅延が発生します (ポーリング間隔によって異なります)。

  2. 原子性: 複数のスレッドが待機している場合、1 つのみがブロック解除されることが保証されます。前述のポーリング ソリューションを使用して同じ動作を保証するには、ロックまたはアトミック命令 (Interlockedクラスで見られるものなど) を使用し、可能なコンパイラおよびプロセッサ命令の並べ替え/メモリ バリアを十分に理解する必要があります。

複数のスレッドを同期する簡単な方法を探している場合、これは .NET で最も単純な (最も単純ではないにしても) ソリューションの 1 つです。プロデューサー/コンシューマー キューの作成は非常に簡単です。

// Simplified example. Check http://www.albahari.com/threading/part2.aspx
// for detailed explanations of this and other syncronizing constructs

private readonly AutoResetEvent _signal = new AutoResetEvent(false);
private readonly ConcurrentQueue<Something> _queue = new ConcurrentQueue<Something>();

// this method can be called by one or more threads simultaneously
// (although the order of enqueued items cannot be known if many threads are competing)
void ProduceItem(Something s)
{
    _queue.Enqueue(s);  // enqueue item for processing
    _signal.Set();      // signal the consumer thread if it's waiting
}

// this loop should be running on a separate thread.
void ConsumerLoop()
{
    while (!_ending)
    {
        // block until producer signals us
        _signal.WaitOne();

        // process whatever is enqueued 
        Something s = null;
        while (!_ending && _concurrentQueue.TryDequeue(out s))
        {
             Process(s);
        }
    }
}

ただし、覚えておく必要があることの 1 つは、 を連続して複数回呼び出してSetも、必ずしもWaitOne複数回通知されるとは限らないということです。この例では、複数のプロデューサーがSetメソッドを起動する可能性がありますが、コンテキストの切り替えが発生して継続するまでに数ミリ秒かかる場合があります。ConsumerLoopつまり、Set効果的に処理されるのは 1 つだけです。

于 2015-10-09T23:31:05.753 に答える
2

スレッドは、AutoResetEvent で WaitOne を呼び出してシグナルを待機します。AutoResetEvent が非シグナル状態の場合、スレッドはブロックされ、現在リソースを制御しているスレッドが Set を呼び出してリソースが使用可能であることを通知するのを待ちます。

Set を呼び出すと、待機中のスレッドを解放するために AutoResetEvent が通知されます。AutoResetEvent は、1 つの待機中のスレッドが解放されるまでシグナル状態のままであり、その後、自動的に非シグナル状態に戻ります。待機しているスレッドがない場合、状態は無期限にシグナル状態のままになります。

于 2015-10-09T11:43:47.930 に答える
0

別のスレッドが event_2.Wait() を使用してイベントを待機しており、スレッドから .Set() を呼び出すと、待機中のスレッドが実行を継続します。

于 2015-10-09T11:44:20.013 に答える