C#

ManualResetEvent

ManualResetEvent like AutoResetEvent is another synchronization techniques in .NET threading. 

ManualResetEvent is used for send signals between two or more threads.

Multiple threads can enter into a waiting/blocking state by calling the WaitOne method on ManualResetEvent object. When controlling thread calls the Set method all the waiting threads are unblocked and free to proceed.

How ManualResetEvent Works

ManualResetEvent maintains a boolean variable in memory. When the boolean variable is false then it blocks all threads and when the boolean variable is true it unblocks all threads.

When we instantiate a ManualResetEvent, we initialize it with default boolean value.

ManualResetEvent manualResetEvent = new ManualResetEvent(false);

In the above code, we initialize the ManualResetEvent with false value, that means all the threads which calls the WaitOne method will block until some thread calls the Set() method.

If we initialize ManualResetEvent with true value, all the threads which calls the WaitOne method will not block and free to proceed further.

WaitOne Method

This method blocks the current thread and wait for the signal by other thread. It returns true if its receives a signal else returns false.

Below is the syntax of calling WaitOne method.

manualResetEvent.WaitOne();

In the second overload of WaitOne method, we can specify the time interval till the current thread wait for the signal. If within time internal, it does not receives a signal it returns false and goes into the next line of method.

Below is the syntax of calling WaitOne method with time interval.

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

We have specify 5 seconds into the WaitOne method. If the manualResetEvent object does not receives a signal between 5 seconds, it set the isSignalled variable to false.

Set Method

This method is used for sending the signal to all waiting threads. Set() Method set the ManualResetEvent object boolean variable to true. All the waiting threads are unblocked and proceed further.

Below is the syntax of calling Set() method.

manualResetEvent.Set();

Reset Method

Once we call the Set() method on the ManualResetEvent object, its boolean remains true. To reset the value we can use Reset() method. Reset method change the boolean value to false.

Below is the syntax of calling Reset method.

manualResetEvent.Reset();

We must immediately call Reset method after calling Set method if we want to send signal to threads multiple times. 

ManualResetEvent Example

The following examples shows how to use ManualResetEvent to release multiple threads. We initialize the ManualResetEvent with false value which will blocks all threads calling WaitOne method. We creates two threads which calls the GetDataFromServer method with server number as parameter.

After getting first set of data both threads wait from the signal from the controlling thread by calling the WaitOne method. When controlling thread calls the Set method on manualrestEvent object. Both threads are released and continue its work. After calling the Set method we immediately called the Reset method which change the boolean value to false. So that if threads again calls the WaitOne method they will block.

After getting the second set of data from server both threads calls the WaitOne method. After waiting for 2 seconds, controlling threads agains calls the Set method to unblock both 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);
    }
}