• 微软示例代码 for ManualResetEvent


    ManualResetEvent

           用于线程同步,通知一个或多个线程某事件已经发生,通常用于一个线程执行的任务必须在其他线程的任务执行之前完成。

           状态分为两种:终止状态和非终止状态。当某一任务完成时,将ManualResetEvent设置为终止状态,这样其他等待的线程(一个或多个)将开始执行自己的任务。

           一旦它被终止,它将保持终止状态,直到它被手动重置

    class Program
    {
        static void Main(string[] args)
        {
            Caclultae calc = new Caclultae();
            Console.WriteLine("Result={0}", calc.result(234).ToString());
            Console.Read();
        }
    }
     
    /// <summary>
    /// 此微软的示例写的非常浅显易懂
    /// 应充分理解这些线程的工作顺序和等待节奏,以及整个程序运行流的顺序
    /// </summary>
    class Caclultae
    {
        double baseNum, firNum, secNum, thdNum;
     
        // 这组信号灯的状态是为 WaitHandle.WaitAll(autoEvents) 准备的
        AutoResetEvent[] autoEvents;
        
        // 这个信号灯是通知所有等待线程开始工作的
        ManualResetEvent manualEvent;
     
        Random Generator;
     
        public Caclultae()
        {
            autoEvents = new AutoResetEvent[]
            {
                new AutoResetEvent(false),
                new AutoResetEvent(false),
                new AutoResetEvent(false)
            };
            manualEvent = new ManualResetEvent(false);
        }
     
        void CalBase(object stateInfo)
        {
            baseNum = Generator.NextDouble();
            Console.WriteLine("BaseNum is Ok");
            manualEvent.Set();
        }
     
        void CalFirst(object stateInfo)
        {
            double preCalc = Generator.NextDouble();
     
            manualEvent.WaitOne();
            Console.WriteLine("FirstNum begins to Calculate");
            firNum = preCalc * baseNum * Generator.NextDouble();
     
            autoEvents[0].Set();
            Console.WriteLine("FirstNum Calculates successfully");
        }
     
        void CalSec(object stateInfo)
        {
            double preCalc = Generator.NextDouble();
            manualEvent.WaitOne();
            Console.WriteLine("SecNum begins to Calculate");
            secNum = preCalc * baseNum * Generator.NextDouble();
            autoEvents[1].Set();
            Console.WriteLine("SecNum  Calculates successfully");
        }
     
        void CalThird(object stateInfo)
        {
            double preCalc = Generator.NextDouble();
            manualEvent.WaitOne();
            Console.WriteLine("ThrdNum begins to Calculate");
            thdNum = preCalc * baseNum * Generator.NextDouble();
            autoEvents[2].Set();
            Console.WriteLine("ThrdNum  Calculates successfully");
        }
     
        public double result(int seed)
        {
            Generator = new Random(seed);
            ThreadPool.QueueUserWorkItem(new WaitCallback(CalBase));
            ThreadPool.QueueUserWorkItem(new WaitCallback(CalFirst));
            ThreadPool.QueueUserWorkItem(new WaitCallback(CalSec));
            ThreadPool.QueueUserWorkItem(new WaitCallback(CalThird));
            
            // 等待指定数组中的所有元素都收到信号
            WaitHandle.WaitAll(autoEvents);
            manualEvent.Reset();
            return firNum + secNum + thdNum;
        }
    }

    CalFirst,CalSec,CalThird都在等待CalBase执行完成。

    当CalBase计算出BaseNum的结果之后,将ManualResetEvent变量设置为终止状态,通知其他三个任务,可以执行他们自己的任务了。

    CalFirst,CalSec,CalThird在分别完成自己的任务后,对自己所属的信号autoEvent数组Set()信号。

    最后,WaitHandle.WaitAll(autoEvents) 条件得以满足,程序继续执行。

    manualEvent.Reset() 必须手动重置 ManualResetEvent ,为下次计算做准备。

    image

  • 相关阅读:
    POJ 1703 Find them, Catch them
    POJ 2236 Wireless Network
    POJ 2010 Moo University
    POJ 2184 Cow Exhibition
    POJ 3280 Cheapest Palindrome
    POJ 3009 Curling 2.0
    POJ 3669 Meteor Shower
    POJ 2718 Smallest Difference
    POJ 3187 Backward Digit Sums
    POJ 3050 Hopscotch
  • 原文地址:https://www.cnblogs.com/SkySoot/p/2567878.html
Copyright © 2020-2023  润新知