Friday, March 19, 2010

Basics about WaitHandle in .NET

WaitHandle is an abstract class under System.Threading namespace. It provides internal works for other synchronization objects inherited from it (for example EventWaitHandle) to block the current thread using its WaitOne(), WaitAny(), WaitAll(), or SignalAndWait() methods. The synchronization objects provide their own implementations to send signal (calling Set() for example) to unblock the thread.

Psudo code action:
---------------------------------------------
static eventWaitHandle1 = new EventWaitHandle;

//call in thread1 to block thread1
eventWaitHandle1.WaitOne();

//Call in thread2 to send signal to unblock thread1
//thread2 needs to hold a reference to eventWaitHandle1
eventWaitHandle1.Set()
---------------------------------------------
Synchronization objects used in this way can have two states: signaled and unsignaled. When in unsignaled state and wait methods are called, calling thread(s) are blocked; When in signaled state, thread(s) blocked on it can pass through. The constructors can defined which state to start with.

There are 2 modes that affect what state (signaled or unsignaled) the object to be in after being signaled. They are defined by EventResetMode Enumeration: EventResetMode.AutoReset and EventResetMode.ManualReset. Synchronization objects' constructors can defined which mode to use.
EventResetMode.AutoReset:
When signaled, the EventWaitHandle resets automatically after releasing a single thread. If no threads are waiting, the EventWaitHandle remains signaled until a thread blocks, and resets after releasing the thread. AutoResetEvent class has this mode built-in.

EventResetMode.ManualReset:
When signaled, the EventWaitHandle releases all waiting threads and remains signaled until it is manually reset (by calling Reset method). ManualResetEvent class has this mode built-in

More details:
If the initial state of the event is nonsignaled, threads that wait on the event will block. If the initial state is signaled, and the ManualReset flag is specified for mode, threads that wait on the event will not block. If the initial state is signaled, and mode is AutoReset, the first thread that waits on the event will be released immediately, after which the event will reset, and subsequent threads will block.

Sample code:
---------------------------------------------
class WaitOneTest
{
static EventWaitHandle ewh = new EventWaitHandle(false, EventResetMode.AutoReset);

public void Test()
{
Thread tr = new Thread(new ParameterizedThreadStart(this.WorkerProc));
tr.Start(ewh);

Console.WriteLine("working in Main");

//block current thread untill ewh get signaled
ewh.WaitOne();

Console.WriteLine("after waitone");

}  //put a breakpint here to see the action

public void WorkerProc(object obj)
{
Console.WriteLine("worker does some work");

//give some time to make clear the effect of signaling
Thread.Sleep(10000);

//send signal but this doesn't mean the blocked thread
//will start right away. The switch is up to the operating system.
((EventWaitHandle)obj).Set();

Console.WriteLine("after calling set");
}
}
---------------------------------------------