C# AutoResetEvent

Summary: in this tutorial, you’ll learn how to use the C# AutoResetEvent class to synchronize threads and control their executions by signaling events between them.

Introduction to the C# AutoResetEvent class

The AutoResetEvent class allows multiple threads to communicate with each other by signaling events.

An AutoResetEvent has two states:

  • Signaled
  • Non-signaled

When an AutoResetEvent object is signaled, a single waiting thread will be released and continues its execution.

However, when an AutoResetEvent object is Unsignaled, the waiting thread will be blocked until the AutoResetEvent becomes signaled again.

The AutoResetEvent object has two main methods that control its state: Waitone() and Set():

  • The WaitOne() method blocks the current thread until the AutoResetEvent is signaled or a timeout interval has elapsed.
  • The Set() method changed the state of the AutoResetEvent to non-signaled and releases a single waiting thread.

In practice, you use the AutoResetEvent in multithreaded applications where one thread needs to wait for another thread to complete its work before continuing.

For example, in a producer-consumer scenario, the consumer thread may wait for the producer thread to produce the data before the consumer thread can consume the data.

To use the AutoResetEvent class, you can follow these steps:

First, create an AutoResetEvent object:

var autoResetEvent = new AutoResetEvent(false);Code language: C# (cs)

The parameter false sets the state of the AutoResetEvent object to Unsignaled.

Second, create one thread that waits for the event to be signaled:

var t = new Thread(() =>
{
    // do some work
    // ...
    // wait for the event to be signaled
    autoResetEvent.WaitOne(); 
    
    // continue execution after the event is signaled
    // do something else
});Code language: C# (cs)

Third, starts the thread:

t.Start();Code language: C# (cs)

Fourth, do some operations before the thread can continue to execute and signal the AutoResetEvent by calling the Set() method:

autoResetEvent.Set();Code language: C# (cs)

The Set() method changes the state of the AutoResetEvent to signaled. As the result, the waiting thread (t) is released and continues the execution until the next call of the WaitOne() method.

Once the thread is released, the AutoResetEvent is automatically reset to the Non-signaled state.

Notice that the AutoResetEvent will be reset automatically after releasing a single waiting thread. To release multiple waiting threads, you need to call the Set() method for each waiting thread or use the ManualResetEvent class instead.

C# AutoResetEvent class example

The following program demonstrates how the AutoResetEvent works:

using static System.Console;

var autoResetEvent = new AutoResetEvent(false);

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

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

    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 t = new Thread(() => DoWork());
t.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
autoResetEvent.Set();

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

WriteLine("Press any key to exit.");
ReadKey();Code language: C# (cs)

How it works.

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

var autoResetEvent = new AutoResetEvent(false);Code language: C# (cs)

Second, define the DoWork() method that represents the operation that a thread will perform:

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

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

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

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 WaitOne() method of the AutoResetEvent object to wait for the event to be signaled.

The WaitOne() method blocks the thread that executes the DoWork() method until the AutoResetEvent object becomes signaled.

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

Third, create and start a new thread that executes the DoWork() method:

var t = new Thread(() => DoWork());
t.Start();Code language: C# (cs)

Fourth, wait for one second to leave enough time for the thread t to run until the WaitOne() method is called:

Thread.Sleep(1000);Code language: C# (cs)

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: C# (cs)

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

autoResetEvent.Set();Code language: C# (cs)

At this moment, the thread that executes the DoWork resumes its execution and displays a message to the console.

Seventh, wait for the thread to complete by calling the Join() method of the Thread class:

t.Join();Code language: C# (cs)

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

WriteLine("Press any key to exit.");
ReadKey();Code language: C# (cs)

The following example shows the output of the program:

Thread 9 is waiting for the event to be signaled...
Waiting for 2 seconds before signaling the event...
Thread 9 has been signaled and has resumed execution.
Press any key to exit.Code language: C# (cs)

Summary

  • Use the C# AutoResetEvent class to synchronize threads and control their executions by signaling events between them.
Was this tutorial helpful ?