ManualResetEvent:
通知一个或多个正在等待的线程已发生事件,允许线程通过发信号互相通信,来控制线程是否可心访问资源。
- Set() : 用于向 ManualResetEvent 发送信号,使其取消阻塞状态(唤醒进程)或者开始阻塞进程,这基于 ManualResetEvent 的初始状态。
- ReSet() : 将 ManualResetEvent 的状态重置至初始状态(即使用 Set() 方法之前的状态)。
- WaitOne() : 使 ManualResetEvent 进入阻塞状态,开始等待唤醒信号。如果有信号,则不会阻塞,直接通过。
- 信号 : new ManualResetEvent(bool arg) ,arg参数就是信号状态,假如为false,则表示当前无信号阻塞线程;如果为true,则有信号不阻塞。
1 static ManualResetEvent _munual = new ManualResetEvent(false); 2 static void Main(string[] args) 3 { 4 _munual.Reset(); 5 for (int i = 0; i <= 3; i++) 6 { 7 Thread th = new Thread(() => 8 { 9 while (true) 10 { 11 _munual.WaitOne(); 12 Print(); 13 Thread.Sleep(1000); 14 } 15 }); 16 th.IsBackground = true; 17 th.Name = "线程" + i; 18 th.Start(); 19 } 20 21 while (true) 22 { 23 Thread.Sleep(2000); 24 Console.WriteLine($"主线程设置信号量"); 25 _munual.Set(); 26 Thread.Sleep(500); 27 _munual.Reset(); 28 } 29 } 30 31 static void Print() 32 { 33 Console.WriteLine($"{Thread.CurrentThread.Name}::{DateTime.Now.ToString("hh:mm:ss-fff")}"); 34 }
AutoResetEvent:
与ManualResetEvent功能类似。
AutoResetEvent(bool initialState):构造函数,用一个指示是否将初始状态设置为终止的布尔值初始化该类的新实例。
false:无信号,子线程的WaitOne方法不会被自动调用
true:有信号,子线程的WaitOne方法会被自动调用
Reset ():将事件状态设置为非终止状态,导致线程阻止;如果该操作成功,则返回true;否则,返回false。
Set ():将事件状态设置为终止状态,允许一个或多个等待线程继续;如果该操作成功,则返回true;否则,返回false。
WaitOne(): 阻止当前线程,直到收到信号。
WaitOne(TimeSpan, Boolean) :阻止当前线程,直到当前实例收到信号,使用 TimeSpan 度量时间间隔并指定是否在等待之前退出同步域。
WaitAll():等待全部信号。
1 static void Main(string[] args) 2 { 3 int current = 0; 4 List <AutoResetEvent> events = new List<AutoResetEvent>(); 5 for (int taskid = 0; taskid < 3; taskid++) 6 { 7 Task.Factory.StartNew(() => 8 { 9 int curr = Interlocked.Increment(ref current); 10 AutoResetEvent evt = new AutoResetEvent(false); 11 events.Add(evt); 12 Console.WriteLine($"Task[{curr}]: working"); 13 Thread.Sleep(current * 1000); 14 Console.WriteLine($"Task[{curr}]: exit"); 15 evt.Set(); 16 }); 17 } 18 Console.WriteLine($"Main wait"); 19 AutoResetEvent.WaitAll(events.ToArray()); 20 Console.WriteLine($"All works are done,Main exit"); 21 Console.ReadKey(); 22 }
两只比较:
AutoResetEvent在一个线程Wait通过后,会自动设置为有信号状态重新阻塞线程。而ManualResetEvent要调用Reset方法重置,否则将一直允许后续其他线程通过。