原文来自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;
}
}
}
整个运行的模型为:
下面为程序的输出结果: