zoukankan      html  css  js  c++  java
  • 微软示例代码 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

  • 相关阅读:
    Django REST framework解析器、渲染器、分页
    微前端qiankun从搭建到部署的实践
    前端开发常用免费资源,显著提升工作效率
    Vue切换页面时碰见过中断axios请求的场景吗?如何中断?
    JavaScript与ES的25个重要知识点!
    电脑端支付宝支付 -前端获取支付宝返回的form 以及submit 调用支付扫码页面
    element ui 分页记忆checked
    通过css改变svg img的颜色
    Howler.js Web音频播放终极解决方案
    5、Redis中对Set类型的操作命令
  • 原文地址:https://www.cnblogs.com/SkySoot/p/2567878.html
Copyright © 2011-2022 走看看