本篇学习了使用ManaualResetEvent和AutoResetEvent类实现线程同步的方案。 (一)代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; //添加命名空间 using System.Threading; //Events类实现线程同步 //AutoResetEvent和ManualResetEvent Event类是.Net的封装器,用于系统级别的内置事件资源的同步 //C#中的event关键字与Threading命名空间中的Event类没有关系 //可以使用事件通知其他的线程:这里有些数据,完成了一些操作等。事件可以发信号,也可以不发信号。 //使用前面的介绍的WaitHandle类,线程可以等待处发信号状态的事件。 //ManualResetEvent用Set()方法发信号,调用Reset()方法,可以使之返回不发信号的状态。如果多个线程在等待一个事件发出信号 //并调用了Set()方法,就释放所有等待的线程。 //如果一个线程刚刚调用了WaitOnce()方法,但事件已经发出了信号等待的线程就可以继续等待。 //AutoResetEvent用Set()方法发信号,调用Reset()方法,可以使之返回不发信号的状态,但是,如果一个线程在等待自动重置的事件发信号 //当第一个线程的等待结束时,该事件会自动变为不发信号的状态。这样,如果多个线程在等待事件发信号,就有一个线程结束其等待状态, //它不是等待时间最长的线程,而是优先级最高的线程。 namespace ThreadStudy { public struct InputData { public int x; public int y; public InputData(int x, int y) { this.x = x; this.y = y; } } public class ThreadTask { private AutoResetEvent autoEvent; private int result; public int Result { get { return result; } } public ThreadTask(AutoResetEvent ev) { this.autoEvent = ev; } public void Calculation(object obj) { InputData data = (InputData)obj; Console.WriteLine("Thread {0} starts calculation", Thread.CurrentThread.ManagedThreadId); Thread.Sleep(new Random().Next(3000)); result = data.x + data.y; Console.WriteLine("Thread {0} is ready", Thread.CurrentThread.ManagedThreadId); //只要完成计算(在随机的一段时间后)就调用AutoResetEvent的Set()方法,向事件发信号。 autoEvent.Set(); } } class Program { static void Main(string[] args) { int taskiCount = 4; AutoResetEvent[] autoEvents = new AutoResetEvent[taskiCount]; ThreadTask[] tasks = new ThreadTask[taskiCount]; for (int i = 0; i < taskiCount; i++) { autoEvents[i] = new AutoResetEvent(false); //每个ThreadTask在构造函数中用一个AutoResetEvent对象初始化,这样每个线程在完成时都有自己的事件对象来发信号 tasks[i] = new ThreadTask(autoEvents[i]); //让后台程序执行计算任务 ThreadPool.QueueUserWorkItem(tasks[i].Calculation, new InputData(i + 1, i + 3)); } for (int i = 0; i < taskiCount; i++) { //WaitHandle类现在用于等待数组中的任意一个事件。WaitAny()等待向任意一个事件发信号 //从WaitAny()返回的index匹配数组中传送给WaitAny()的事件,以提供向哪个事件发信号的信息。 //并从这个事件中读取结果。 int index = WaitHandle.WaitAny(autoEvents); if (index == WaitHandle.WaitTimeout) { Console.WriteLine("TimeOut!!!"); } else { Console.WriteLine("finished task for {0},rsult:{1}", index, tasks[index].Result); } } Console.Read(); } } } (二)运行截图: