ManualResetEvent
threading
C#
synchronization
programming-tutorial

How to find what state ManualResetEvent is in?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

A ManualResetEvent is either signaled or non-signaled, but the important detail is that there is no dedicated property on ManualResetEvent that tells you its current state. In concurrent code, that is intentional: even if you could read the state, another thread could change it immediately afterward, so a plain state check is rarely a reliable coordination mechanism.

The Closest Thing to a State Check

If you only need to know whether the event is signaled at this instant, you can call WaitOne(0). A timeout of 0 means "do not block."

csharp
1using System;
2using System.Threading;
3
4class Program
5{
6    static void Main()
7    {
8        using var gate = new ManualResetEvent(false);
9
10        Console.WriteLine(gate.WaitOne(0)); // False
11        gate.Set();
12        Console.WriteLine(gate.WaitOne(0)); // True
13        gate.Reset();
14        Console.WriteLine(gate.WaitOne(0)); // False
15    }
16}

For ManualResetEvent, this is safe in the sense that it does not consume the signal. If the event is signaled, it stays signaled until some thread calls Reset.

What WaitOne(0) does not give you is a stable fact about the future. Another thread can call Reset right after the check, which means code like "if signaled, then assume I can proceed later" is still racy.

That is why most correct code does not ask "what state is it in?" very often. It asks the event to coordinate the next action immediately, either by waiting or by setting and resetting it at well-defined points in the workflow.

Why Polling Is Usually the Wrong Design

A synchronization event is meant to coordinate waiting threads, not to act like a shared boolean flag that code inspects casually. If your logic depends on the event state being visible as application state, keep that state separately and protect it appropriately.

For example, if you own the component, wrap the event and the state together:

csharp
1using System.Threading;
2
3public sealed class Gate
4{
5    private readonly ManualResetEvent _event = new(false);
6    private int _isOpen;
7
8    public bool IsOpen => Volatile.Read(ref _isOpen) == 1;
9
10    public void Open()
11    {
12        Volatile.Write(ref _isOpen, 1);
13        _event.Set();
14    }
15
16    public void Close()
17    {
18        Volatile.Write(ref _isOpen, 0);
19        _event.Reset();
20    }
21
22    public void Wait() => _event.WaitOne();
23}

Now IsOpen represents your own application state, and the event is the synchronization primitive used to block or release threads.

This split is especially useful when you also need logging, metrics, or UI display. Those concerns want a durable business state, while the synchronization primitive is only about waking threads efficiently.

Consider ManualResetEventSlim When Appropriate

If you only need an in-process synchronization primitive and you want a built-in readable state, ManualResetEventSlim exposes IsSet.

csharp
1using System;
2using System.Threading;
3
4class Program
5{
6    static void Main()
7    {
8        var gate = new ManualResetEventSlim(false);
9        Console.WriteLine(gate.IsSet); // False
10        gate.Set();
11        Console.WriteLine(gate.IsSet); // True
12    }
13}

That said, the same concurrency rule still applies: IsSet is only a momentary observation. It is useful for diagnostics or guarded logic, but it is not a substitute for correct synchronization.

Common Pitfalls

  • Looking for a direct State property on ManualResetEvent. It does not exist.
  • Treating WaitOne(0) as a durable guarantee. Another thread can change the event immediately after the call.
  • Using event state as ordinary business state. Keep those concepts separate when your code needs both.
  • Replacing waiting logic with polling loops. That wastes CPU and often makes races harder to reason about.
  • Forgetting that WaitOne(0) is only a snapshot. It can help with diagnostics, but it should not become the center of your threading design.

Summary

  • 'ManualResetEvent has no direct public property for its current state.'
  • 'WaitOne(0) tells you whether it is signaled at that instant without blocking.'
  • That check is still only a snapshot and can race with other threads.
  • If your design needs explicit state, track it separately in your own class.
  • 'ManualResetEventSlim offers an IsSet property when an in-process alternative is acceptable.'

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.