ManualResetEvent&ManualResetEventSlim

ManualResetEvent

ManualResetEvent有三个重要的方法,分别为:waiteone(),set(),reset(),其含义如下:

1.WaitOne()即等待信号发出,即可往下运行。

2.set()发出信号,让线程方法继续往下运行,并允许其他线程(如有)一并往下运行。

3.reset()重新初始化(即:去掉票据)变为ManualResetEvent(false)形式。

官方示例如下:

internal class Program
{
    private static ManualResetEvent mre = new ManualResetEvent(false);
    static void Main()
    {
        Console.WriteLine("\n初始化3个线程,并在遇到waitone时阻塞运行:\n");
        for (int i = 0; i <= 2; i++)
        {
            Thread t = new Thread(ThreadProc);
            t.Name = "Thread_" + i;
            t.Start();
        }

        Thread.Sleep(500);
        Console.WriteLine("\n三个线程已经启动,请按回车键调用Set()方法来释放3个阻塞线程");
        Console.ReadLine();

        mre.Set();

        Thread.Sleep(500);
        Console.WriteLine("\n当这个ManualResetEvent活得信号,3个线程都会从WaitOne()方法内返回,并继续运行(如果有新线程被创建)不会被阻塞,可按回车键进行观察:\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("\n按回车键调用 Reset()方法(设置为无信号状态),重新初始化一个线程运行,并在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("\n按回车键调用 Set() 方法,然后结束演示.");
        Console.ReadLine();

        mre.Set();
        Console.ReadLine();
    }

    private static void ThreadProc()
    {
        string name = Thread.CurrentThread.Name;
        Console.WriteLine(name + " starts and calls mre.WaitOne()");
        mre.WaitOne();
        Console.WriteLine(name + " ends.");
    }
}

运行结果:

ManualResetEventSlim:

ManualResetEventSlim是ManualResetEvent的简化版或者叫优化版,其主要原理为采用了自旋方式来提高性能,适用于短期内等待的情况,性能比后者要好很多。适用于一次写入,多次读取时候的线程同步场景。

官方示例代码:

 internal class Program
 {
     static void Main(string[] args)
     {
         MRES_SetWaitReset();
         Console.ReadKey();
     }
     static void MRES_SetWaitReset()
     {
         ManualResetEventSlim mres1 = new ManualResetEventSlim(false);
         ManualResetEventSlim mres2 = new ManualResetEventSlim(false);
         ManualResetEventSlim mres3 = new ManualResetEventSlim(true); 

         var observer = Task.Factory.StartNew(() =>
         {
             mres1.Wait();
             Console.WriteLine("mres1!阻塞结束继续运行");
             Console.WriteLine("mres3即将被重置");
             mres3.Reset(); 
             Console.WriteLine("mres2即将获取到票据");
             mres2.Set();
         });

         Console.WriteLine("主线程: mres3.IsSet = {0} (should be true)", mres3.IsSet);
         Console.WriteLine("主线程:mres1即将获取信号");
         mres1.Set();
         Console.WriteLine("主线程:mres2即将阻塞");
         mres2.Wait();
         Console.WriteLine("主线程:mres2已获取信号!");
         Console.WriteLine("主线程: mres3.IsSet = {0} (should be false)", mres3.IsSet);
observer.Wait();
// make sure that this has fully completed mres1.Dispose(); mres2.Dispose(); mres3.Dispose(); } }

运行结果:

 

posted @ 2024-10-19 22:04  Shapley  阅读(31)  评论(0编辑  收藏  举报