原文来自mituan1234567,本文有所节选。
在多动作的自动控制领域,经常会使用到多线程,如线程A等待信号a才触发,线程B等待信号b才会触发,而线程C可能需要多个信号才会满足触发条件,这时候就需要使用System.Threading.WaitHandle.WaitAll。
下面是节选的实例:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace WaitAllDemo { class Program { double baseNumber, firstTerm, secondTerm, thirdTerm; AutoResetEvent[] autoEvents; ManualResetEvent manualEvent; //产生随机数的类. Random random; static void Main(string[] args) { Program demo = new Program(); Console.WriteLine("Result= {0}.", demo.Result(234).ToString()); Console.ReadLine(); } //构造函数 public Program() { autoEvents = new AutoResetEvent[] { new AutoResetEvent(false), new AutoResetEvent(false), new AutoResetEvent(false) }; manualEvent = new ManualResetEvent(false); } //计算基数 void CalculateBase(object stateInfo) { baseNumber = random.NextDouble(); Console.WriteLine("base number= " + baseNumber.ToString()); //指示基数已经算好. manualEvent.Set(); } //计算第一项 void CalculateFirstTerm(object stateInfo) { //生成随机数 double preCalc = random.NextDouble(); //等待基数以便计算. manualEvent.WaitOne(); //通过preCalc和baseNumber计算第一项. firstTerm = preCalc * baseNumber * random.NextDouble(); Console.WriteLine("first Term= " + firstTerm.ToString()); //发出信号指示计算完成. autoEvents[0].Set(); } //计算第二项 void CalculateSecondTerm(object stateInfo) { double preCalc = random.NextDouble(); manualEvent.WaitOne(); secondTerm = preCalc * baseNumber * random.NextDouble(); Console.WriteLine("second Term= " + secondTerm.ToString()); autoEvents[1].Set(); } //计算第三项 void CalculateThirdTerm(object stateInfo) { double preCalc = random.NextDouble(); manualEvent.WaitOne(); thirdTerm = preCalc * baseNumber * random.NextDouble(); Console.WriteLine("third Term= " + thirdTerm.ToString()); autoEvents[2].Set(); } //计算结果 public double Result(int seed) { random = new Random(seed); //同时计算 ThreadPool.QueueUserWorkItem(new WaitCallback(CalculateFirstTerm)); ThreadPool.QueueUserWorkItem(new WaitCallback(CalculateSecondTerm)); ThreadPool.QueueUserWorkItem(new WaitCallback(CalculateThirdTerm)); ThreadPool.QueueUserWorkItem(new WaitCallback(CalculateBase)); //计算基数,同时设置信号 //等待所有的信号. WaitHandle.WaitAll(autoEvents); //重置信号,以便等待下一次计算. manualEvent.Reset(); //返回计算结果 return firstTerm + secondTerm + thirdTerm; } } }
整个运行的模型为:
下面为程序的输出结果: