All about multithreading.

Thursday, September 6, 2007

EventWaitHandler: AutoResetEvent and ManualResetEvent

WaitHandler
Threads can communicate using WaitHandlers by signaling. Mutex, Semapore and EventWaitHandle are derived from WaitHandle class.

EventWaitHandle
There are two types of EventWaitHandlers. AutoResetEvent and ManualResetEvent. AutoResetEvent lets one waiting thread at a time when Set() is called but ManualResetEvent lets all waiting threads to pass by when Set() is called. ManualResetEvent starts blocking when Reset() is called.

AutoResetEvent
This acts like a turnstile which lets one at a time. When a thread hits WaitOne(), it waits till some other thread calls Set(). Take a look at the following picture. Thread1, Thread2 and Thread3 are waiting after calling WaitOne(). For every Set() call from another thread, one thread will pass the turnstile.

I have created a simple application to test this. There are two buttons to span a thread DoWork. DoWork has WaitOne call and it blocks threads. Third button calls Set() to release one thread at a time. Click first two buttons to span thread and click third button twice to release blocked threads.

private EventWaitHandle wh = new AutoResetEvent(false);
private void DoWork()
{
Console.WriteLine(Thread.CurrentThread.Name + ": Waiting for Set() notification");
// Wait for notification
//
wh.WaitOne();
Console.WriteLine(Thread.CurrentThread.Name + ": Notified");
}
private void buttonCreateThreadOne_Click(object sender, EventArgs e)
{
Thread a = new Thread(DoWork);
// You can name the thread!.. for debugging purpose
a.Name = "A";
a.Start();
}
private void buttonCreateSecondThread_Click(object sender, EventArgs e)
{
Thread b = new Thread(DoWork);
// You can name the thread!.. for debugging purpose
b.Name = "B";
b.Start();
}
private void buttonReleaseOneThread_Click(object sender, EventArgs e)
{
wh.Set();
}

Please note that the code after WaitOne call in DoWork is not thread safe. A call to Set will let next waiting thread to enter even the first thread is still executing the code.


ManualResetEvent
This is like a gate which lets more than one at a time. When a thread hits WaitOne(), it waits till someother thread calls Set(). Take a look at the following picture. Thread1, Thread2 and Thread3 are waiting after calling WaitOne(). When Set is called from another thread, all waiting thereads will pass the gate.


Code snippet to illustrate the above.

private void buttonFirstThread_Click(object sender, EventArgs e)
{
Thread a = new Thread(DoWork);
// You can name the thread!.. for debugging purpose
a.Name = "A";
a.Start();
}
private void buttonSecondThread_Click(object sender, EventArgs e)
{
Thread b = new Thread(DoWork);
// You can name the thread!.. for debugging purpose
b.Name = "B";
b.Start();
}
private void buttonCallSet_Click(object sender, EventArgs e)
{
wh.Set();
}
private void buttonCallReset_Click(object sender, EventArgs e)
{
wh.Reset();
}
Download the project.

4 comments:

Sanjay Singh said...

Really awesome explanation.

Niraj Sevalkar said...

such a great explanation with good example please put these type of explanation for all concept of c#

John Ortiz OrdoƱez said...

Thanks a lot for this.

I have created my own post (in Spanish) about event based synchronization:

http://ortizol.blogspot.com/2014/07/receta-c-no-4-8-sincronizar-la-ejecucion-de-multiples-threads-usando-un-evento.html

Agains, thanks for the awesome explanation about AutoResetEvent, y ManualResetEvent.

See you later.

www said...

Thank you!!!

Blog Archive

About Me

One of my friends said "if you want to learn something, write a book about it". I wanted to learn all about multithreading and instead of writing a book, I am trying to blog. Thank you for stopping. I appreciate your feedback. Sreekanth