We can use Wait
and Pulse
to simulate a ManualResetEvent
as follows:
code #1
readonly object _locker = new object();
bool _signal;
void WaitOne()
{
lock (_locker)
{
while (!_signal) Monitor.Wait (_locker);
}
}
void Set()
{
lock (_locker)
{ _signal = true;
Monitor.PulseAll (_locker);
}
}
void Reset()
{
lock (_locker) _signal = false;
}
fine
now lets talk about enhancing it to be AutoREsetEvent
:
an AutoResetEvent
is simply a matter of replacing the code in WaitOne
with this:
code #2
lock (_locker)
{
while (!_signal) Monitor.Wait (_locker);
_signal = false;//<---------------
}
and replacing PulseAll
with Pulse
in the Set
method:
code #3
lock (_locker)
{ _signal = true;
Monitor.Pulse (_locker);
}
and here is the question :
at code #2 , the line _signal = false;
.
why is it necessary ? Pulse
will only reach 1 wait handle and I know that AutoREsetEvent
is letting only one blocked item to go through and automatically close the gate.
so why writing _signal = false
is necessary ? .
If the _signal
variable stays true
, then if another thread calls WaitOne
after the Set
call, it wouldn't wait. You don't just have to consider how existing waiting threads are handled - you have to consider the overall state of the object.