Master Managed Threading and Synchronization Techniques (cont'd)
Signaling using EventWaitHandle
Wait handles provide simple and powerful thread synchronization using signaling, where threads wait for each other's signal to bring them out of the wait state. Wait handles can be local or named system wide. They have two modes: AutoReset and ManualReset modes. In AutoReset mode, a single thread is released and the event automatically gets reset. In ManualReset mode, threads are released until the event gets reset manually. You'll see examples of both. Here's the AutoReset example:
advertisement


   // AutoResetEvent example
   class Program
   {
      private static EventWaitHandle ewh = 
         new EventWaitHandle(false, EventResetMode.AutoReset);
      static void Main(string[] args)
      {
         Thread th;
         for (int i = 0; i < 2; i++)
         {
            th = new Thread(new ThreadStart(PrintThreadId));
            th.Start();
         }
         for (int i = 0; i < 2; i++)
         {
            Console.ReadLine();
            ewh.Set();
         }
      }
      public static void PrintThreadId()
      {
         Console.WriteLine("Thread ID:{0} waiting," 
            Thread.CurrentThread.ManagedThreadId);
         ewh.WaitOne();
         Console.WriteLine("Thread ID:{0} enters code block," 
            Thread.CurrentThread.ManagedThreadId);
      }
   }
The program outputs the following text:

   Thread ID:3 waiting
   Thread ID:4 waiting
   <enter key here>
   Thread ID:3 enters code block
   <enter key here>
   Thread ID:4 enters code block
As you can see, in AutoReset mode, each execution of the Set method releases one thread.

In contrast, consider the code below, which demonstrates using the ManualReset mode:

   // ManualResetEvent example
      class Program
      {
         private static EventWaitHandle ewh = 
            new EventWaitHandle(false, EventResetMode.ManualReset);
   
         static void Main(string[] args)
         {
            Thread th;
            for (int i = 0; i < 2; i++)
            {
               th = new Thread(new ThreadStart(PrintThreadId));
               th.Start();
            }
            Console.ReadLine();
            ewh.Set();
         }
         public static void PrintThreadId()
         {
            Console.WriteLine("Thread ID:{0} waiting," 
               Thread.CurrentThread.ManagedThreadId);
            ewh.WaitOne();
            Console.WriteLine("Thread ID:{0} enters code block," 
               Thread.CurrentThread.ManagedThreadId);
         }
      }
Finally, here's the output of the ManualReset mode program:

   Thread ID:3 waiting
   Thread ID:4 waiting
   <enter key here>
   Thread ID:4 enters code block
   Thread ID:3 enters code block
Choosing a Synchronization Technique
Choosing the appropriate synchronization technique isn't difficult, but because there are so many possibilities, it can be difficult to remember which technique is appropriate for any particular situation. Table 2 can help; it shows a summary of the various synchronization techniques, along with each technique's unique features.

Table 2. Synchronization Techniques: This quick and handy guide shows the main features of each synchronization technique to help you determine which technique might be the most appropriate in a given situation.
Technique Main Feature
Lock/Monitor Synchronizes access to code regions.
Mutex Same as Lock/Monitor but can work system-wide.
Interlocked Use when performing atomic arithmetic operations and comparisons. Avoid dirty read scenarios.
Read—Writer Useful when there are many read-only threads but fewer writer threads.
Semaphores Controls the number of threads that can access a resource at any point in time.
EventWaitHandle Threads participate in synchronization by signaling each other.

With all these synchronizing techniques in hand, you'll find that you can safely introduce threading operations to your applications, while also limiting the possibility of threading problems.

Previous Page: Read-Writer Locks and Semaphores  


Vikas Goyal is a Microsoft MVP solutions architect with several years of industry experience. He is mainly involved in designing products and solutions for the financial industry. You can contact him through his web site or his blog.
Page 1: IntroductionPage 5: Interlocked Operations
Page 2: Thread ManagementPage 6: Read-Writer Locks and Semaphores
Page 3: Synchronization TechniquesPage 7: Signaling using EventWaitHandle
Page 4: Synchronization with Mutexes