问题抽象:当某个操作的执行必须依赖于另一个操作的完成时,需要有个机制来保证这种先后关系。
线程通信方案:ManualResetEventSlim、ManualResetEvent、AutoResetEvent
方案特性:提供线程通知的能力,没有接到通知前,线程必须等待,有先后顺序。
1、ManualResetEvent类
对象有两种信号量状态True和False。构造函数设置初始状态。简单来说,
◆ 如果构造函数由true创建,则第一次WaitOne()不会阻止线程的执行,而是等待Reset后的第二次WaitOne()才阻止线程执行。
◆ 如果构造函数有false创建,则WaitOne()必须等待Set()才能往下执行。
一句话总结就是:是否忽略第一次阻塞。
方法如下:
◆ WaitOne:该方法用于阻塞线程,默认是无限期的阻塞,支持设置等待时间,如果超时就放弃阻塞,不等了,继续往下执行;
◆ Set:手动修改信号量为True,也就是恢复线程执行;
◆ ReSet:重置状态; 重置后,又能WaitOne()啦
using System; using System.Threading; namespace ConsoleApp1 { class Program { //一开始设置为false才会等待收到信号才执行 static ManualResetEvent mr = new ManualResetEvent(false); public static void Main() { Thread t = new Thread(Run); //启动辅助线程 t.Start(); //等待辅助线程执行完毕之后,主线程才继续执行 Console.WriteLine("主线程一边做自己的事,一边等辅助线程执行!" + DateTime.Now.ToString("mm:ss")); mr.WaitOne(); Console.WriteLine("收到信号,主线程继续执行" + DateTime.Now.ToString("mm:ss")); Console.ReadKey(); } static void Run() { //模拟长时间任务 Thread.Sleep(3000); Console.WriteLine("辅助线程长时间任务完成!" + DateTime.Now.ToString("mm:ss")); mr.Set(); } } }