Wednesday, April 29, 2009

AutoResetEvent and ManualResetEvent

This example is good for analysis:(Example from: http://www.java2s.com/Tutorial/CSharp/0420__Thread/AutoResetEventinaction.htm)

using System;
using System.Threading;

public class MainClass
{
public static AutoResetEvent A = new AutoResetEvent(false);
public static int index = 0;

public static int Main(){
Timer T = new Timer(new TimerCallback(TimerHandler), null, 5000, 10000);

A.WaitOne();
Console.WriteLine("Main Thread event signaled");
T.Dispose();
return 0;
}
public static void TimerHandler(object state)
{
Console.WriteLine("TimerHandler");
if (index == 5)
A.Set();

index++;
Console.WriteLine(index);
}
}

Let's Analysize the above code:
1. public static AutoResetEvent A = new AutoResetEvent(false);
here the boolean parameter for the AutoResetEvent represents the initial state, when it is false, it is set as non-signaled.
2. The System.Threading.Timer use the TimerCallback predefined delegate to call the function TimerHandler(), the second thread is created and run.
3. The main Thread goes to WaitOne() method, and blocked to wait the second thread to signal the main thread to go.
4. The Timer get the second function to be invoke after 5000 miliseconds and run every 10000 miliseconds. See the details of how to use Timer() function.
5. In the second thread when the index goes to 5, it send the signal using Set() method, the main thread is set as non-signaled at the beginning and after second thread use Set() to signal the main thread, the main thread become signaled and proceed to execute.
6. Main Thread and second thread both execute until finished.

About the difference of AutoResetEvent and ManualResetEvent is that AutoResetEvent is like a tollbooth, when a car passes by, it automatically closing before the next on can go through but ManualRest is like a door, need to be closed( use Reset() method). And AutoReset will allow only one single waiting thread to continue while ManualResetEvent allows all the threads which is waiton to continue until you use Reset() to stop.

The following codes give an example:

using System;
using System.Threading;

namespace ManualAutoReset
{
class Program
{
delegate void Executor();

private static XXXResetEvent e= new XXXResetEvent(false);

static void Main(string[] args)
{
new Executor(Teste1).BeginInvoke(null, null);
new Executor(Teste2).BeginInvoke(null, null);
new Executor(Teste3).BeginInvoke(null, null);

Console.WriteLine("Fim");
Console.ReadLine();
}
static void Teste1()
{
Console.WriteLine("Teste1 - Begin");

Thread.Sleep(5000);
e.Set();

Console.WriteLine("Teste1 - End");
}

static void Teste2()
{
Console.WriteLine("Teste2 - Begin");
_resetEvent.WaitOne();
Console.WriteLine("Teste2 - End");
}

static void Teste3()
{
Console.WriteLine("Teste3 - Begin");
_resetEvent.WaitOne();
Console.WriteLine("Teste3 - End");
}
}
}

XXX can be Auto or Manual here. If XXX is set to Manual, both thread2 and thread3 will execute. If XXX is Auto, only one in thread2 and thread3 will continue because when one thread is signaled and execute the ResetEvent object is set to false again.

When create or open a named ResetEvent, we need to use EventWaitHandle.
For example the following code shows how to open or create a named event:

EventWaitHandle myEvent=null;
try
{
myEvent=EventWaitHandle.OpenExisting("MyEvent");
}
catch(WaitHandleCannotBeOpenedException)
{
}

if(myEvent==null)
{
myEvent=new EventWaitHandle(false, EventResetMode.AutoReset, "MyEvent");
}

No comments: