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
object is Unsignaled, the waiting thread will be blocked until the AutoResetEvent
becomes signaled again.AutoResetEvent
The AutoResetEvent
object has two main methods that control its state: Waitone()
and Set()
:
- The
WaitOne()
method blocks the current thread until theAutoResetEvent
is signaled or a timeout interval has elapsed. - The
Set()
method changed the state of theAutoResetEvent
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
object to be signaled by calling the AutoResetEvent
Set()
method of the
object:AutoResetEvent
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.