AutoResetEvent在Set之后立即重置

Rot*_*tem 7 c# multithreading autoresetevent

考虑以下模式:

private AutoResetEvent signal = new AutoResetEvent(false);

private void Work()
{
    while (true)
    {
        Thread.Sleep(5000);
        signal.Set();
        //has a waiting thread definitely been signaled by now?
        signal.Reset();
    }
}

public void WaitForNextEvent()
{
    signal.WaitOne();
}
Run Code Online (Sandbox Code Playgroud)

此模式的目的是允许外部消费者等待某个事件(例如 - 消息到达).WaitForNextEvent不是从课堂内调用的.

举一个应该熟悉的例子,考虑一下System.Diagnostics.Process.它公开了一个Exited事件,但它也公开了一个WaitForExit方法,它允许调用者同步等待,直到进程退出.这就是我想在这里实现的目标.

我需要的原因signal.Reset()是,如果一个线程调用WaitForNextEvent 之后 signal.Set()已经被调用(或者换句话说,如果.Set没有线程在等待时调用),它会立即返回,因为事件已经预先发出信号.

这个问题

  • 是否保证在调用之前WaitForNextEvent()将发出一个线程调用信号?如果没有,实施方法的其他解决方案是什么? signal.Reset()WaitFor

Mat*_*son 6

而不是使用AutoResetEventManualResetEvent,使用此:

public sealed class Signaller
{
    public void PulseAll()
    {
        lock (_lock)
        {
            Monitor.PulseAll(_lock);
        }
    }

    public void Pulse()
    {
        lock (_lock)
        {
            Monitor.Pulse(_lock);
        }
    }

    public void Wait()
    {
        Wait(Timeout.Infinite);
    }

    public bool Wait(int timeoutMilliseconds)
    {
        lock (_lock)
        {
            return Monitor.Wait(_lock, timeoutMilliseconds);
        }
    }

    private readonly object _lock = new object();
}
Run Code Online (Sandbox Code Playgroud)

然后像这样更改你的代码:

private Signaller signal = new Signaller();

private void Work()
{
    while (true)
    {
        Thread.Sleep(5000);
        signal.Pulse(); // Or signal.PulseAll() to signal ALL waiting threads.
    }
}

public void WaitForNextEvent()
{
    signal.Wait();
}
Run Code Online (Sandbox Code Playgroud)