10

次のパターンを検討してください。

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();
}

このパターンの目的は、外部コンシューマーが特定のイベント (メッセージの到着など) を待機できるようにすることです。WaitForNextEventクラス内からは呼び出されません。

よく知られている例として、 を考えてみましょうSystem.Diagnostics.Process。イベントを公開しますが、プロセスが終了するまで呼び出し元が同期的に待機できるようにExitedするメソッドも公開します。WaitForExitこれが私がここで達成しようとしていることです。

私が必要な理由は、既に呼び出された後signal.Reset()にスレッドが呼び出された場合 (つまり、スレッドが待機していないときに呼び出された場合)、イベントが既に通知されているため、すぐに戻るためです。WaitForNextEvent signal.Set().Set

質問

  • スレッド呼び出しが呼び出される前WaitForNextEvent()に通知されることが保証されていますか? そうでない場合、メソッドを実装するための他のソリューションは何ですか? signal.Reset()WaitFor
4

4 に答える 4

8

AutoResetEventまたはを使用する代わりにManualResetEvent、これを使用します。

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();
}

次に、コードを次のように変更します。

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();
}
于 2013-09-04T10:29:54.073 に答える