2009-04-10 4 views
0

ThreadAとThreadBの両方が、同じAutoResetEventでこの順にWaitOne()を呼び出すとします。イベントが設定されると、なぜThreadAの代わりにThreadBが解放されるのですか?2番目のスレッドは、WaitOne()を呼び出してAutoResetEventによって解放されたときに、最初のスレッドが最初のスレッドの前に解放されるのはなぜですか?

私はあなたがみとめスレッドが待機している上AutoResetEventを設定するときに何が起こるかを調べるためにテストを実行しました:

private static void Test() 
    { 
     // two threads - waiting for the same autoreset event 
     // start it unset i.e. closed i.e. anything calling WaitOne() will block 
     AutoResetEvent autoEvent = new AutoResetEvent(false); 

     Thread thread1 = new Thread(new ThreadStart(WriteSomeMessageToTheConsole)); 
     thread1.Start(); // this will now block until we set the event 

     Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole)); 
     thread2.Start(); // this will now also block until we set the event 

     // simulate some other stuff 
     Console.WriteLine("Doing stuff..."); 
     Thread.Sleep(5000); 
     Console.WriteLine("Stuff done."); 

     // set the event - I thought this would mean both waiting threads are allowed to continue 
     // BUT thread2 runs and thread1 stays blocked indefinitely 
     // So I guess I was wrong and that Set only releases one thread in WaitOne()? 
     // And why thread2 first? 
     autoEvent1.Set(); 
    } 

コードはもちろん有用ではないのです。それは単なるミッキーマウスの例です。そして、これは重要ではない/緊急です。しかし、私はとにかくもっと知りたいと思うでしょう...

+0

autoEvent1.Set()を呼び出してみます。もう一方のスレッドが解放されるかどうかを再度確認します。私はスイッチを2回回す必要があると思います。 –

+0

こんにちは - 私はこれを直後に試しました - 私はSet()への2番目の呼び出しを続行するために2番目のスレッドを得ることができます。 Thread.Sleep()を呼び出して –

+0

私は現在、解放されたスレッドがランダムであることを誰かが実際に知っているかどうかを調べることにもっと興味があります。ドキュメンテーションによると、スレッドは何らかの並べ替えを示すためにキューに入れられています(最初のスレッドが最初にリリースされる予定だった理由です)。 –

答えて

2

IIRCは、指定されていない。誰もが言及したように、あなたが条件をブロードキャストしたい場合は、手動リセットイベントをしたい。あなたはリリースしたい場合

実際の注文が期待していたものとは異なる理由を実際に掘り下げたい場合は、「Windows Internals」を参照してください。マーク・ルシノビッチが書いたことは何でもあります。チャンスはどこかで経営幹部の待遇命令を説明することです。

0

AutoResetEventでは、Setは1つのスレッドのみをリリースします。待機中の複数のスレッドを解放するには、ManualResetEventを使用する必要があります。

+0

OK - 確認していただきありがとうございます - なぜ2番目のスレッドが最初にリリースされるのか?これはいつもそうだと思うのでしょうか、それともWaitOne()を呼び出す最後のスレッドで、Set()への別の呼び出しを待たなければならないのでしょうか? –

+0

btw :)を使ってください。私はまだ不思議です。 –

+0

私はそれがちょうどチャンスだと思う。 –

1

MSDN

ManualResetEvent上

MSDNから:「制御 スレッドが活動を完了すると ManualResetEventにWAITONEを呼び出すスレッド は 信号を待って、ブロックする、それことを知らせるために設定し 呼び出し。

すべての待機中のスレッドがリリースされている。 スレッドが進むことができます待っしかしAutoResetEvent、MSD用Nはこう言います: "AutoResetEventを に設定すると、待機中のスレッドが解放されます。 待機中のスレッドがにリリースされ、自動的に が非シグナリング状態に戻るまで、AutoResetEventは通知されたままです。 スレッドが待機していない場合、状態 は無期限に通知されたままです。

は、「自動リセットイベントによって解放されたスレッド

関連する問題