在多线程开发中,时常用到 ManualResetEvent 与 AutoResetEvent 。 它们如同道路交通中的信号灯。两者之间有什么区别呢?
共同点:
均继承 EventWaitHandle 接口,因此,均具有以下功能:
Reset() //红灯
Set() //绿灯
WaitOne() // 等待信号
ManualResetEvent mre = new ManualResetEvent(false);红灯
AutoResetEvent auto = new ManualResetEvent(false);红灯
不同点:
AutoResetEvent 收到 Set 后 , 一次只能执行一个线程,其它线程继续 WaitOne 。
ManualResetEvent 收到 Set 后,所有处理 WaitOne 状态线程均继续执行
class Program { static void Main(string[] args) { //注意:ManualResetEvent可以对所有进行等待的线程进行统一控制 //true-初始状态为发出信号;false-初始状态为未发出信号 ManualResetEvent mre = new ManualResetEvent(false); //线程池开启10个线程 for (int i = 0; i < 10; i++) { int k = i; ThreadPool.QueueUserWorkItem(t => { Console.WriteLine($"这是第{k+1}个线程,线程ID为{Thread.CurrentThread.ManagedThreadId}"); //等待信号,没有信号的话不会执行后面的语句,因为初始状态是false,所以后面的语句暂时不会执行 mre.WaitOne(); Console.WriteLine($"第{k+1}个线程获得信号,线程ID为{Thread.CurrentThread.ManagedThreadId}"); }); } Thread.Sleep(5000); Console.WriteLine(" 5秒后发出信号... "); //Set()方法:释放信号,所有等待信号的线程都将获得信号,开始执行WaitOne()后面的语句 mre.Set(); Console.ReadKey(); } }
执行结果如图
可见,没有信号时,WaitOne()后面的语句都不执行(被阻塞),当Set()释放信号后,所有阻塞的线程都开始继续执行。