Open
Description
The docs for AutoResetEvent
say:
There is no guarantee that every call to the Set method will release a thread. If two calls are too close together, so that the second call occurs before a thread has been released, only one thread is released. It's as if the second call did not happen.
This reads to me as if the following scenario could happen:
- 2 threads are waiting on the event
- 2 calls to Set() are made in rapid succession
- Only one thread is released
This seems like a pretty major issue! However, I'm wondering whether this bug is actually real and if so whether more information can be provided about it. It could also be that I'm misinterpreting the scenario described in which case perhaps the docs could be clarified.
Some notes:
- I tried to reproduce this scenario on .NET 7 Windows and failed to do so. I used a program like this:
using var @event = new AutoResetEvent(false);
const int Threads = 100;
var b = new Barrier(Threads + 1);
var tasks = Enumerable.Range(0, Threads).Select(t => Task.Factory.StartNew(() => { b.SignalAndWait(); @event.WaitOne(); }, TaskCreationOptions.LongRunning)).ToArray();
b.SignalAndWait(); // wait for all threads to spin up
Thread.Sleep(3000); // give them time to start waiting on the event
for (var i = 0; i < Threads; ++i) { @event.Set(); } // call Set() in rapid succession
// making all the Set() calls from different threads also seems to work
//b = new Barrier(Threads);
//for (var i = 0; i < Threads; ++i) { Task.Factory.StartNew(() => { b.SignalAndWait(); @event.Set(); }, TaskCreationOptions.LongRunning); }
Console.WriteLine(Task.WaitAll(tasks, TimeSpan.FromSeconds(10))); // True only if each Set() released a thread
EventWaitHandle
(the parent class) does not mention this issue in its docs that I could find.