Introduction to the usage of ManualResetEvent in C #

Brief introduction

Multiple threads can enter a waiting or blocking state by calling the waitonone method of the ManualResetEvent object. When the control thread calls the Set() method, all waiting threads will resume and continue to execute.

How does ManualResetEvent work

A bool value is maintained in memory. If the bool value is False, all threads will be blocked. On the contrary, if the bool value is True, all threads will exit blocking. When we create an instance of the ManualResetEvent object, we pass the default bool value in the function construction. The following is an example of instantiating the ManualResetEvent.

ManualResetEvent manualResetEvent = new ManualResetEvent(false);

In the above code, we initialize a ManualResetEvent object with a value of False, which means that all threads calling waitonone will be blocked until a thread calls the Set() method. If we initialize the ManualResetEvent object with the value True, all threads calling the WaitOne method will not be blocked and can be executed later.

WaitOne method

This method blocks the current thread and waits for other threads to send signals. If it receives a signal, it returns True, otherwise it returns False. The following demonstrates how to call this method.

manualResetEvent.WaitOne();

In the second overloaded version of the WaitOne method, we can specify the time interval for the current thread to wait for a signal. If no signal is received within the time interval, the method returns False and continues execution. The following code demonstrates the WaitOne call with a time interval parameter.

bool isSignalled = manualResetEvent.WaitOne(TimeSpan.FromSeconds(5));

We specify 5 seconds as the parameter of the WaitOne method. If the manualResetEvent object receives a signal within 5 seconds, it assigns isSignalled to False.

Set method

This method is used to send signals to all waiting threads. The call of the Set() method makes the bool variable value of the ManualResetEvent object True, and all threads are released and continue to execute. The following is an example of a call:

manualResetEvent.Set();

Reset method

Once we call the Set() method of the ManualResetEvent object, its bool value becomes true. We can call the Reset() method to Reset the value, and the Reset() method resets the value to False. The following is an example of calling the Reset method:

manualResetEvent.Reset();

If we want to send signals multiple times, we must call the Reset() method immediately after calling the Set() method.

ManualResetEvent example

The following example shows how to use ManualResetEvent to free multiple threads. We instantiate the ManualResetEvent object with a false value, which will block all threads calling the WaitOne method. We created two threads that call the method GetDataFromServer with the number of servers as a parameter. After calling the WaitOne method to obtain the first batch of quantities, both threads wait for a signal from the calling WaitOne thread. When the control thread calls the Set method of the manualrestEvent object, both threads are released and continue to run. After calling the Set method, we immediately called the Reset method, which will change the bool value of the manualrestEvent object to false. Therefore, if threads call the WaitOne method again, they will still be blocked. After getting the second batch of data from the server, both threads called the WaitOne method. After 2 seconds, the control thread calls the Set method again to release the two threads.

class Program
{
  static ManualResetEvent manualResetEvent = new ManualResetEvent(false);
 
  static void Main(string[] args)
  {
    Task task = Task.Factory.StartNew(() =>
    {
      GetDataFromServer(1);
    });
 
    Task.Factory.StartNew(() =>
    {
      GetDataFromServer(2);
    });
 
 
    //Send first signal to get first set of data from server 1 and server 2
    manualResetEvent.Set();
    manualResetEvent.Reset();
 
    Thread.Sleep(TimeSpan.FromSeconds(2));
    //Send second signal to get second set of data from server 1 and server 2
    manualResetEvent.Set();
 
    Console.ReadLine();
 
    /* Result
      * I get first data from server1
      * I get first data from server2
      * I get second data from server1
      * I get second data from server2
      * All the data collected from server2
      * All the data collected from server1
      */
  }
 
  static void GetDataFromServer(int serverNumber)
  {
    //Calling any webservice to get data
    Console.WriteLine("I get first data from server" + serverNumber);
    manualResetEvent.WaitOne();
 
    Thread.Sleep(TimeSpan.FromSeconds(2));
    Console.WriteLine("I get second data from server" + serverNumber);
    manualResetEvent.WaitOne();
    Console.WriteLine("All the data collected from server" + serverNumber);
  }
}

Posted on Mon, 01 Nov 2021 07:31:27 -0400 by PHP-beginner