C# ManualResetEventSlim

Summary: in this tutorial, you’ll learn how to use the C# ManualResetEventSlim to provide a way for threads to communicate with each other.

Introduction to the C# ManualResetEventSlim class

The ManualResetEventSlim class allows threads to wait for a signal from another thread before continuing execution. In other words, the ManualResetEventSlim class allows you to synchronize the execution of multiple threads.

Like an AutoResetEvent object, a ManualResetEventSlim object has two states:

  • Signaled
  • Non-signaled

The ManualResetEventSlim class is called “Manual” because once the event is signaled, it remains signaled until you manually reset it.

Also, the ManualResetEventSlim class is called “Slim” because it is a lightweight implementation of the ManualResetEvent class. The ManualResetEventSlim is optimized for performance and uses less memory than the ManualResetEvent class.

To use the ManualResetEventSlim class, you follow these steps:

First, create a new ManualResetEventSlim object:

var resetEvent = new ManualResetEventSlim(false);Code language: JavaScript (javascript)

The false argument, which we pass the constructor, sets the initial state of the event to non-signaled.

Second, create one or more threads that wait for the event to be signaled:

var t = new Thread(() => {
    // do some work
    // ...
    // wait for the event to be signaled
    resetEvent.Wait();

    // continue the execution after the event is signaled
});Code language: JavaScript (javascript)

The Wait() method will block the waiting threads until the event is signaled.

Third, start the thread:

t.Start();Code language: CSS (css)

Fourth, signal the event by calling the Set() method on the ManualResetEventSlim object:

resetEvent.Set();Code language: CSS (css)

The Set() method releases all the threads that waiting on the event to resume their executions until the next Reset() method is called on the ManualResetEventSlim object.

Fifth, call the Reset() method of the ManualResetEventSlim object to reset the state to non-signaled, which blocks all the waiting threads:

resetEvent.Reset();Code language: CSS (css)

C# ManualResetEventSlim example

The following program demonstrates how the ManualResetEventSlim class works:

using static System.Console;

var resetEvent = new ManualResetEventSlim(false);

void DoWork()
{
    WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} is waiting for the event to be signaled...");

    // Wait for the event to be signaled
    resetEvent.Wait();

    WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} has been signaled and has resumed execution.");
}

// Create a thread that wait for the event to be signaled and start it
var t1 = new Thread(() => DoWork());
var t2 = new Thread(() => DoWork());

t1.Start();
t2.Start();

// Wait for 1s to let the thread runs for a while 
Thread.Sleep(1000);

// Wait for 2s before signaling the event
WriteLine("Waiting for 2 seconds before signaling the event...");
Thread.Sleep(2000);


// Signal the event
resetEvent.Set();

// Wait for the threads to finish
t1.Join();
t2.Join();


WriteLine("Press any key to exit.");
ReadKey();
Code language: JavaScript (javascript)

Output:

Thread 10 is waiting for the event to be signaled...
Thread 11 is waiting for the event to be signaled...
Waiting for 2 seconds before signaling the event...
Thread 11 has been signaled and has resumed execution.
Thread 10 has been signaled and has resumed execution.
Press any key to exit.
Code language: PHP (php)

How it works.

First, create a new ManualResetEventSlim object and initialize it with false, indicating that the event is not signaled initially:

var resetEvent = new ManualResetEventSlim(false);Code language: JavaScript (javascript)

Second, define the DoWork() method that the waiting threads will execute:

void DoWork()
{
    WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} is waiting for the event to be signaled...");

    // Wait for the event to be signaled
    resetEvent.Wait();

    WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} has been signaled and has resumed execution.");
}Code language: JavaScript (javascript)

The DoWork() method writes a message to the console indicating that the thread is waiting for the event to be signaled. It then calls the Wait() method of the ManualResetEventSLim object to wait for the event to be signaled.

The Wait() method blocks the threads that execute the DoWork() method until the ManualResetEventSlim object becomes signaled.

When the ManualResetEventSlim is signaled, the method resumes its execution that writes another message to the console.

Third, create two threads that execute the DoWork() method and start them immediately:

// Create threads that wait for the event to be signaled and start them
var t1 = new Thread(() => DoWork());
var t2 = new Thread(() => DoWork());

t1.Start();
t2.Start();
Code language: JavaScript (javascript)

Fourth, wait for one second to leave enough time for the threads to run until the Wait() method is called:

Thread.Sleep(1000);Code language: CSS (css)

Fifth, write a message to the console and wait for two seconds before signaling the event:

WriteLine("Waiting for 2 seconds before signaling the event...");
Thread.Sleep(2000);Code language: JavaScript (javascript)

Sixth, change the state of the ManualEventResetSlim object to be signaled by calling its Set() method:

// Signal the event
resetEvent.Set();Code language: JavaScript (javascript)

After this call, the threads that execute the DoWork() method resume their executions and display messages to the console.

Seventh, wait for the threads to complete by calling the Join() method:

// Wait for the threads to finish
t1.Join();
t2.Join();
Code language: JavaScript (javascript)

Finally, wait for the user to press any key to exit the program:

WriteLine("Press any key to exit.");
ReadKey();Code language: JavaScript (javascript)

Summary

  • Use a C# ManualResetEvent class to represent a thread synchronizing event that allows one or more threads to wait for the event to occur.
Was this tutorial helpful ?