autoresetevent和manualresetevent

时间:2011-10-12 05:48:20

标签: c#

using System;
using System.Threading;

public class Example
{
    // mre is used to block and release threads manually. It is
    // created in the unsignaled state.
    private static ManualResetEvent mre = new ManualResetEvent(false);

    static void Main()
    {
        Console.WriteLine("\nStart 3 named threads that block on a ManualResetEvent:\n");

        for(int i = 0; i <= 2; i++)
        {
            Thread t = new Thread(ThreadProc);
            t.Name = "Thread_" + i;
            t.Start();
        }

        Thread.Sleep(500);
        Console.WriteLine("\nWhen all three threads have started, press Enter to call Set()" +
                          "\nto release all the threads.\n");
        Console.ReadLine();

        mre.Set();

        Thread.Sleep(500);
        Console.WriteLine("\nWhen a ManualResetEvent is signaled, threads that call WaitOne()" +
                          "\ndo not block. Press Enter to show this.\n");
        Console.ReadLine();

        for(int i = 3; i <= 4; i++)
        {
            Thread t = new Thread(ThreadProc);
            t.Name = "Thread_" + i;
            t.Start();
        }

        Thread.Sleep(500);
        Console.WriteLine("\nPress Enter to call Reset(), so that threads once again block" +
                          "\nwhen they call WaitOne().\n");
        Console.ReadLine();

        mre.Reset();

        // Start a thread that waits on the ManualResetEvent.
        Thread t5 = new Thread(ThreadProc);
        t5.Name = "Thread_5";
        t5.Start();

        Thread.Sleep(500);
        Console.WriteLine("\nPress Enter to call Set() and conclude the demo.");
        Console.ReadLine();

        mre.Set();

        // If you run this example in Visual Studio, uncomment the following line:
        //Console.ReadLine();
    }

    //thread entry point
    private static void ThreadProc()
    {
        string name = Thread.CurrentThread.Name;

        Console.WriteLine(name + " starts and calls mre.WaitOne()");
        //wait untill signaled   
        mre.WaitOne();

        Console.WriteLine(name + " ends.");
    }
}

我写了一个例子来了解autoresetevent和manualresetevent。 但是,当我们必须使用Autoresetevent和手动重新同步时,还不清楚吗? 以上就是这个例子。请提供我们可以使用的真实场景 基于事件的同步。

1 个答案:

答案 0 :(得分:3)

有一些地方使用这种东西。我个人通常更喜欢Monitor.Wait / Pulse,但有时{Manual / Auto} ResetEvent更有用 - 尤其是您希望能够在多个句柄上等待的地方

我见过这两个最明显的案例是:

  • 生产者/消费者队列:当队列为空时,消费者将在监视器上等待或等待句柄。然后,生产者将在添加项目时脉冲/设置监视器/句柄,以唤醒消费者,因此它知道它有工作要做。
  • 唤醒“休眠”线程,让它知道它可以退出:拥有while(!ShouldStop) { Work(); Wait(10000); }种循环并不罕见; “停止”线程可以再次使等待线程唤醒,注意已经设置了“停止”标志

这些情况当然非常类似,毫无疑问还有更多 - 但这些是我经常看到的。