AutoResetEvent and ManualResetEvent in C#

AutoResetEvent and ManualResetEvent are used in threading and help us to manage synchronization using signals.

For example, suppose there are 2 threads, Thread1 and Thread2 and 1 main thread created by the Main() method.

Thread1 and Thread2 is doing some task and the Main thread is also doing some task (perhaps printing numbers). Now, we want to implement synchronization between these threads.

Let's play with an example.

First, we'll look at AutoResetEvent and then ManualResetEvent.

We'll understand both the concepts using their outputs, to understand the execution flow between these threads, our program is implemented in a colorful way. The following table shows the colors and their use in the program.

Color Used for
Cyan Method Title (in other words AutoReset / ManualReset)
Yellow Used for Thread1 and Thread2
Green Used for Main Thread
Magenta Displays name of the Current Running Thread

Create a new Console application named “AutoResetEventAndManulResetEvent” with the 2 Methods AutoResetMethod() and ManualResetEvent().

Program.cs

  1. class Program  
  2.     {  
  3.         static ConsoleColor prevColor = Console.ForegroundColor;  
  4.         static AutoResetEvent autoReset = new AutoResetEvent(false);  
  5.         static ManualResetEvent manualReset = new ManualResetEvent(false);  
  6.         static void Main(string[] args)  
  7.         {  
  8.             Console.Title = "AutoResetEvent and ManualResetEvent";  
  9.             Thread t1 = new Thread(new ThreadStart(AutoResetMethod));  
  10.             Thread t2 = new Thread(new ThreadStart(ManualResetMethod));  
  11.             t1.Name = "Thread1";  
  12.             t2.Name = "Thread2";  
  13.             Thread.CurrentThread.Name = "Main Thread";  
  14.   
  15.             t1.Start();      // Please Uncomment this while using AutoResetEvent.  
  16.             //t2.Start();   // Please Uncomment this while using ManualResetEvent.  
  17.   
  18.             Console.ReadLine();  
  19.             Console.WriteLine("Thread1 Paused for Task1...");  
  20.             Console.ForegroundColor = ConsoleColor.Magenta;  
  21.             Console.WriteLine("\t\t\tRunning Thread: {0}",Thread.CurrentThread.Name);  
  22.             Console.ForegroundColor = ConsoleColor.Green;  
  23.             Console.WriteLine("Executing Task on Main Thread....");  
  24.             for (int i = 0; i < 5; i++)  
  25.             {  
  26.                 Console.Write(" {0}", i);  
  27.                 Thread.Sleep(1000);  
  28.             }  
  29.             Console.WriteLine();  
  30.             Console.WriteLine("Task Completed on Main Thread....");  
  31.             //manualReset.Set();    // Please Uncomment this while using ManualResetEvent.  
  32.             autoReset.Set();        // Please Uncomment this while using AutoResetEvent.  
  33.   
  34.             Console.ReadLine();  
  35.             Console.ForegroundColor = ConsoleColor.Magenta;  
  36.             Console.WriteLine("\t\t\tRunning Thread: {0}", Thread.CurrentThread.Name);  
  37.             Console.ForegroundColor = ConsoleColor.Green;  
  38.             Console.WriteLine("Thread1 Paused for Task2...");  
  39.             Console.WriteLine("Doing some work in Main Thread......");  
  40.             //manualReset.Set();     // Please Uncomment this while using ManualResetEvent.  
  41.             autoReset.Set();        // Please Uncomment this while using AutoResetEvent.  
  42.             Console.ForegroundColor = prevColor;  
  43.         }  
  44.   
  45.         static void ManualResetMethod()  
  46.         {  
  47.             Console.ForegroundColor = ConsoleColor.Cyan;  
  48.             Console.WriteLine("\t\t***************** ManualResetEvent ***************");  
  49.             Console.ForegroundColor = ConsoleColor.Magenta;  
  50.             Console.WriteLine("\t\t\tRunning Thread: {0}", Thread.CurrentThread.Name);  
  51.             Console.ForegroundColor = ConsoleColor.Yellow;  
  52.             Console.WriteLine("Executing Task1......");  
  53.             Console.WriteLine("Press Enter to Pause Task1..");  
  54.             //Wait for first task:  
  55.             manualReset.WaitOne();  
  56.             Console.ForegroundColor = ConsoleColor.Magenta;  
  57.             Console.WriteLine("\t\t\tRunning Thread: {0}", Thread.CurrentThread.Name);  
  58.             Console.ForegroundColor = ConsoleColor.Yellow;  
  59.             Console.WriteLine("\n===================================");  
  60.             Console.WriteLine("Executing Task1.....");  
  61.             for (int i = 0; i < 5; i++)  
  62.             {  
  63.                 Console.WriteLine("Task1 executing.....");  
  64.                 Thread.Sleep(1000);  
  65.             }  
  66.             Console.WriteLine("Execution of Task1 completed..");  
  67.             Console.WriteLine("===================================");  
  68.             Console.WriteLine();  
  69.             Console.WriteLine("===================================");  
  70.             Console.WriteLine("Executing Task2......");  
  71.             Console.WriteLine("Press Enter to Pause Task2..");  
  72.             //Wait for second task:  
  73.             manualReset.WaitOne();  
  74.             Console.ForegroundColor = ConsoleColor.Magenta;  
  75.             Console.WriteLine("\t\t\tRunning Thread: {0}", Thread.CurrentThread.Name);  
  76.             Console.ForegroundColor = ConsoleColor.Yellow;  
  77.             Console.WriteLine("Execution of Task2 completed...");  
  78.             Console.WriteLine("===================================");  
  79.             Console.ForegroundColor = prevColor;  
  80.         }  
  81.   
  82.         static void AutoResetMethod()  
  83.         {  
  84.             Console.ForegroundColor = ConsoleColor.Cyan;  
  85.             Console.WriteLine("\t\t***************** AutoResetEvent ***************");  
  86.             Console.ForegroundColor = ConsoleColor.Magenta;  
  87.             Console.WriteLine("\t\t\tRunning Thread: {0}", Thread.CurrentThread.Name);  
  88.             Console.ForegroundColor = ConsoleColor.Yellow;  
  89.             Console.WriteLine("Executing Task1......");  
  90.             Console.WriteLine("Press Enter to Pause Task1..");  
  91.             //Wait for first task:  
  92.             autoReset.WaitOne();  
  93.             Console.ForegroundColor = ConsoleColor.Magenta;  
  94.             Console.WriteLine("\t\t\tRunning Thread: {0}", Thread.CurrentThread.Name);  
  95.             Console.ForegroundColor = ConsoleColor.Yellow;  
  96.             Console.WriteLine("\n===================================");  
  97.             Console.WriteLine("Executing Task1.....");  
  98.             for (int i = 0; i < 5; i++)  
  99.             {  
  100.                 Console.WriteLine("Task1 executing.....");  
  101.                 Thread.Sleep(1000);  
  102.             }              
  103.             Console.WriteLine("Execution of Task1 completed..");  
  104.             Console.WriteLine("===================================");  
  105.             Console.WriteLine();  
  106.             Console.WriteLine("===================================");  
  107.             Console.WriteLine("Executing Task2......");  
  108.             Console.WriteLine("Press Enter to Pause Task2..");  
  109.             //Wait for second task:  
  110.             autoReset.WaitOne();  
  111.             Console.ForegroundColor = ConsoleColor.Magenta;  
  112.             Console.WriteLine("\t\t\tRunning Thread: {0}", Thread.CurrentThread.Name);  
  113.             Console.ForegroundColor = ConsoleColor.Yellow;  
  114.             Console.WriteLine("Execution of Task2 completed...");  
  115.             Console.WriteLine("===================================");  
  116.             Console.ForegroundColor = prevColor;  
  117.         }  
  118.     } 

In the preceding example, 2 Threads are created, in other words Thread1 and Thread2.

AutoResetMethod() is running on Thread1 and ManualResetMethod() is running on Thread2 and the others are running on the main thread.

the same logic is used in both methods.

To use AutoResetEvent and ManualResetEvent in your program, create an object of AutoResetEvent and ManualResetEvent, that provides 2 methods for pausing and starting any thread as shown in the following table.

Method Description
WaitOne() Block the current thread until WaitHandler receives a signal
Set() Allow one or more waiting threads to proceed.

Always remember that, for every WaitOne() we should have a Set() that actually releases the paused thread.

So, first we'll see the functionality of AutoResetEvent, (while running AutoResetEvent, please comment t2 Thread and ManualResetEvent objects and vice-a-versa).

Thread1 points to AutoResetMethod() and Thread2 points to ManualResetMethod() that contains some code that performs 2 Tasks.

The main thread's task is to print some numbers.

Run the program. (While running AutoResetEvent please comment “manualReset.WaitOne();”and while running ManualResetEvent please comment “autoReset.WaitOne();”at both the places in Main()).

Output (AutoResetEvent):



So, when you run the program in AutoResetEvent mode, Thread1 will start Task1 (in Yellow color) and it'll ask you to press ENTER to pause that thread (using WaitOne()).

Once ENTER is pressed, Thread1 will pause Task1 and control will directly shift to Main Thread where Mai Thread will perform its task, in other words to print numbers (in Green Color). As soon as Main Thread completes its task, it'll send a signal to Thread1 (using Set()) that was paused and Thread1 will start its execution again for Task1.

After completion of Task1, Thread1 will start Task2 and again it'll ask you to press ENTER to pause the thread, again control will shift to the main thread to perform its task and after completion of task it'll return back to Thread1. Thread1 will complete the remaining task and after completion closes the program.

Output (ManualResetEvent):



When you run the program in ManualResetEvent mode, Thread2 will start Task1 (in Yellow color) and it'll ask you to press ENTER to pause that thread (using WaitOne()).

After pressing ENTER, Thread2 will pause Task1 and control will directly shift to Main Thread where Main Thread will perform its task, in other words print numbers (in Green Color).

Now watch here carefully, as soon as the main thread completes its task, of printing numbers, using the first Set() method it'll send a signal to Thread2 to begin its execution. Thread2 will begin its execution and after completion of Task1, Thread2 will start Task2 and it'll again ask you to press ENTER to pause Thread2, but as soon as control reaches the second WaitOne() the control will not be shifted to the main thread, instead the program will continue its execution and will start and complete Task2 as well. Now control will leave ManualResetEvent().

Now, press ENTER, because the control is in Main(), after Pressing ENTER the main thread will complete its task and your program will close.

This happened because, in the case of ManualResetEvent, 1 Set() method will revokes all the WaitOne() methods and this is the main difference between AutoResetEvent and ManualResetEvent.

Conclusion

When we use AutoResetEvent, for every WaitOne(), we must call Set(). But when we use ManualResetEvent() 1 Set() will revoke all the WaitOne() in our program.

I hope this article helps you to understand the difference between AutoResetEvent and ManualResetEvent.

If there's any mistake in this article please let me know. Please provide your valuable feedback and comments, that enable me to provide a better article the next time.


Similar Articles