Using an Event Synchronization Object


C# supports another type of synchronization object: the event. There are two types of events: manual reset and auto reset. These are supported by the classes ManualResetEvent and AutoResetEvent. Beginning with C# 2.0, these classes are now derived from the top-level class EventWaitHandle. These classes are used in situations in which one thread is waiting for some event to occur in another thread. When the event takes place, the second thread signals the first, allowing it to resume execution.

The constructors for ManualResetEvent and AutoResetEvent are shown here:

 public ManualResetEvent(bool status) public AutoResetEvent(bool status)

Here, if status is true, the event is initially signaled. If status is false, the event is initially non-signaled.

Events are easy to use. For a ManualResetEvent, the procedure works like this. A thread that is waiting for some event simply calls WaitOne( ) on the event object representing that event. WaitOne( ) returns immediately if the event object is in a signaled state. Otherwise, it suspends execution of the calling thread until the event is signaled. The thread that generates the event begins by calling Reset( ), which causes the event object to enter a non-signaled state. After that thread performs the event, it sets the event object to a signaled state by calling Set( ). Thus, a call to Set( ) can be understood as signaling that an event has occurred. When the event object is set to a signaled state, the call to WaitOne( ) will return and the first thread will resume execution.

The difference between AutoResetEvent and ManualResetEvent is how the event gets reset. For ManualResetEvent, the event remains signaled until a call to Reset( ) is made. For AutoResetEvent, the event automatically changes to a non-signaled state as soon as a thread waiting on that event receives the event notification and resumes execution. Thus, a call to Reset( ) is not necessary when using AutoResetEvent.

Here is an example that illustrates ManualResetEvent:

 // Use a manual event object. using System; using System.Threading; // This thread signals the event passed to its constructor. class MyThread {   public Thread thrd;   ManualResetEvent mre;   public MyThread(string name, ManualResetEvent evt) {     thrd = new Thread(this.run);     thrd.Name = name;     mre = evt;     thrd.Start();   }   // Entry point of thread.   void run() {     Console.WriteLine("Inside thread " + thrd.Name);     for(int i=0; i<5; i++) {       Console.WriteLine(thrd.Name);       Thread.Sleep(500);     }     Console.WriteLine(thrd.Name + " Done!");     // Signal the event.     mre.Set();   } } class ManualEventDemo {   public static void Main() {     ManualResetEvent evtObj = new ManualResetEvent(false);     MyThread mt1 = new MyThread("Event Thread 1", evtObj);     Console.WriteLine("Main thread waiting for event.");     // Wait for signaled event.     evtObj.WaitOne();          Console.WriteLine("Main thread received first event.");     // Reset the event.     evtObj.Reset();     mt1 = new MyThread("Event Thread 2", evtObj);     // Wait for signaled event.     evtObj.WaitOne();     Console.WriteLine("Main thread received second event.");   } }

The output is shown here.

 Inside thread Event Thread 1 Event Thread 1 Main thread waiting for event. Event Thread 1 Event Thread 1 Event Thread 1 Event Thread 1 Event Thread 1 Done! Main thread received first event. Inside thread Event Thread 2 Event Thread 2 Event Thread 2 Event Thread 2 Event Thread 2 Event Thread 2 Event Thread 2 Done! Main thread received second event.

First, notice that MyThread is passed a ManualResetEvent in its constructor. When MyThread’s run( ) method finishes, it calls Set( ) on that event object, which puts the event object into a signaled state. Inside Main( ), a ManualResetEvent called evtObj is created with an initially unsignaled state. Then, a MyThread instance is created and passed evtObj. Next, the main thread waits on the event object. Because the initial state of evtObj is not signaled, this causes the main thread to wait until the instance of MyThread calls Set( ), which puts evtObj into a signaled state. This allows the main thread to run again. This process is repeated for the second thread. Without the use of the event object, all threads would have run simultaneously and their outputs would have been jumbled. To verify this, try commenting-out the call to WaitOne( ) inside Main( ).

In the preceding program, if an AutoResetEvent object rather than a ManualResetEvent object is used, then the call to Reset( ) in Main( ) would not be necessary. The reason is that the event is automatically set to a non-signaled state when a thread waiting on the event is resumed. To try this, simply change all references to ManualResetEvent to AutoResetEvent and remove the call to Reset( ). This version will execute the same as before.




C# 2.0(c) The Complete Reference
C# 2.0: The Complete Reference (Complete Reference Series)
ISBN: 0072262095
EAN: 2147483647
Year: 2006
Pages: 300

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net