views:

212

answers:

3

I ran a test to find out what happens when you set an AutoResetEvent on which mutiple threads are waiting:

    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();
    }

The code is of course not useful; it's just a mickey mouse example. And this is not important/urgent. But I'd be interested to know more anyway...

A: 

On an AutoResetEvent, Set only releases one thread. You should use a ManualResetEvent to release multiple waiting threads.

JP Alioto
OK - thanks for the confirmation - any idea why the second thread gets released first? Is it just chance that this seems to always be the case or is it always the last thread calling WaitOne() that will get released (and the others have to wait for another call to Set()?
J M
I gather it's not how you would use it btw :). I'm still curious though.
J M
I think it's just chance.
J.W.
Seems logical since you block it last that it will overwite t1's wait and get woken by the set. I.e. last one to block wins. Not 100% sure of this, with threads, it's best to assume it's random. :)
JP Alioto
A: 

From MSDN

MSDN on ManualResetEvent: "Threads that call WaitOne on the ManualResetEvent will block, awaiting the signal. When the controlling thread completes the activity, it calls Set to signal that the waiting threads can proceed. All waiting threads are released.

But for AutoResetEvent, MSDN says: "Calling Set signals AutoResetEvent to release a waiting thread. AutoResetEvent remains signaled until a single waiting thread is released, and then automatically returns to the nonsignaled state. If no threads are waiting, the state remains signaled indefinitely.

"

J.W.
+2  A: 

IIRC, which thread is released by an auto-reset event is unspecified. As everyone else mentioned, you want a manual reset event if you want to broadcast a condition. If you want to release an exact number (say exactly 3 of n), then you probably want to use a semaphore.

If you really want to dig into why the order might be different than you would expect, take a look at "Windows Internals" or anything that Mark Russinovich has written. Chances are that he explains the wait order on executive resources somewhere.

D.Shawley
Thank you :) This will do me nicely.
J M