ManualResetEvent ,AutoResetEvent 都可以阻塞线程执行,直到收到set()信号,线程被释放。
ManualResetEvent 和AutoResetEvent不同点是 前者需要手动调用Reset()重置,才会继续去阻塞线程,
后者是自动被Reset();所以针对多个线程被阻塞时,ManualResetEvent 调用一次Set() 即可释放所有线程。
AutoResetEvent由于自动被重置了,所以每个线程都需要调用一次Set() 才能被释放。
如下实例定义多个线程:
using System; using System.Threading; public class Example { // mre手动阻塞和释放线程. 构造参数initalState为初始状态,false为无信号状态(遇到WaitOne方法,会阻塞) // true为有信号状态(遇到WaitOne方法,会直接执行) private static ManualResetEvent mre = new ManualResetEvent(false); static void Main() { Console.WriteLine("\nStart 3 named threads that block on a ManualResetEvent:\n"); for (int i = 0; i <= 2; i++) { Thread t = new Thread(ThreadProc); t.Name = "Thread_" + i; t.Start(); } Thread.Sleep(500); Console.WriteLine("\nWhen all three threads have started, press Enter to call Set()" + "\nto release all the threads.\n"); Console.ReadLine(); //设置状态,允许一个或多个线程从阻塞状态继续执行,这时被阻塞的线程会全部执行。 mre.Set(); Thread.Sleep(500); Console.WriteLine("\nWhen a ManualResetEvent is signaled, threads that call WaitOne()" + "\ndo not block. Press Enter to show this.\n"); Console.ReadLine(); //这里的两个线程中的WaitOne()是不会阻塞的,因为这个时候没有重置状态,此时的状态还是true for (int i = 3; i <= 4; i++) { Thread t = new Thread(ThreadProc); t.Name = "Thread_" + i; t.Start(); } Thread.Sleep(500); Console.WriteLine("\nPress Enter to call Reset(), so that threads once again block" + "\nwhen they call WaitOne().\n"); Console.ReadLine(); //重置状态,此时下面的线程5 遇到WaitOne()会阻塞 mre.Reset(); // Start a thread that waits on the ManualResetEvent. Thread t5 = new Thread(ThreadProc); t5.Name = "Thread_5"; t5.Start(); Thread.Sleep(500); Console.WriteLine("\nPress Enter to call Set() and conclude the demo."); Console.ReadLine(); mre.Set(); // If you run this example in Visual Studio, uncomment the following line: //Console.ReadLine(); } private static void ThreadProc() { string name = Thread.CurrentThread.Name; Console.WriteLine(name + " starts and calls mre.WaitOne()"); //阻塞线程往下执行 mre.WaitOne(); Console.WriteLine(name + " ends."); } } /* This example produces output similar to the following: Start 3 named threads that block on a ManualResetEvent: Thread_0 starts and calls mre.WaitOne() Thread_1 starts and calls mre.WaitOne() Thread_2 starts and calls mre.WaitOne() When all three threads have started, press Enter to call Set() to release all the threads. Thread_2 ends. Thread_0 ends. Thread_1 ends. When a ManualResetEvent is signaled, threads that call WaitOne() do not block. Press Enter to show this. Thread_3 starts and calls mre.WaitOne() Thread_3 ends. Thread_4 starts and calls mre.WaitOne() Thread_4 ends. Press Enter to call Reset(), so that threads once again block when they call WaitOne(). Thread_5 starts and calls mre.WaitOne() Press Enter to call Set() and conclude the demo. Thread_5 ends. */
using System; using System.Threading; // AutoResetEvent 自动重置信号进行阻塞, // 当设置Set()后会自动重置成false状态进行阻塞。 class Example { //true 信号,表示现在的状态为非阻塞状态, //第一个到达线程,遇到第一个WaitOne()会直接通过,其它线程会被阻塞。 private static AutoResetEvent event_1 = new AutoResetEvent(true); private static AutoResetEvent event_2 = new AutoResetEvent(false); static void Main() { Console.WriteLine("Press Enter to create three threads and start them.\r\n" + "The threads wait on AutoResetEvent #1, which was created\r\n" + "in the signaled state, so the first thread is released.\r\n" + "This puts AutoResetEvent #1 into the unsignaled state."); Console.ReadLine(); for (int i = 1; i < 4; i++) { Thread t = new Thread(ThreadProc); t.Name = "Thread_" + i; t.Start(); } Thread.Sleep(250); //event_1初始值为true,所以这里这里只需要对剩下的两个线程进行Set() for (int i = 0; i < 2; i++) { Console.WriteLine("Press Enter to release another thread."); Console.ReadLine(); event_1.Set(); Thread.Sleep(250); } Console.WriteLine("\r\nAll threads are now waiting on AutoResetEvent #2."); //event_2初始状态为false 所以三个线程需要三次被释放。 for (int i = 0; i < 3; i++) { Console.WriteLine("Press Enter to release a thread."); Console.ReadLine(); event_2.Set(); Thread.Sleep(250); } // Visual Studio: Uncomment the following line. //Console.Readline(); } static void ThreadProc() { string name = Thread.CurrentThread.Name; Console.WriteLine("{0} waits on AutoResetEvent #1.", name); //由于event_1信号初始为true,所以第一个到达线程会直接通过。随即信号被自动重置为了false。 //其他线程被阻塞,当调用Set()方法的时候,当前线程会通过,随机又会自动重置为false, //每个线程需要执行一次Set(). //与ManualResetEvent 不同的是,ManualResetEvent 需要手工设置Reset(),所以在手工没有重置之前,所有线程都会被释放。 //AutoResetEvent自动重置,每个线程都需要被Set()才能被释放。 event_1.WaitOne(); Console.WriteLine("{0} is released from AutoResetEvent #1.", name); Console.WriteLine("{0} waits on AutoResetEvent #2.", name); event_2.WaitOne(); Console.WriteLine("{0} is released from AutoResetEvent #2.", name); Console.WriteLine("{0} ends.", name); } } /* This example produces output similar to the following: Press Enter to create three threads and start them. The threads wait on AutoResetEvent #1, which was created in the signaled state, so the first thread is released. This puts AutoResetEvent #1 into the unsignaled state. Thread_1 waits on AutoResetEvent #1. Thread_1 is released from AutoResetEvent #1. Thread_1 waits on AutoResetEvent #2. Thread_3 waits on AutoResetEvent #1. Thread_2 waits on AutoResetEvent #1. Press Enter to release another thread. Thread_3 is released from AutoResetEvent #1. Thread_3 waits on AutoResetEvent #2. Press Enter to release another thread. Thread_2 is released from AutoResetEvent #1. Thread_2 waits on AutoResetEvent #2. All threads are now waiting on AutoResetEvent #2. Press Enter to release a thread. Thread_2 is released from AutoResetEvent #2. Thread_2 ends. Press Enter to release a thread. Thread_1 is released from AutoResetEvent #2. Thread_1 ends. Press Enter to release a thread. Thread_3 is released from AutoResetEvent #2. Thread_3 ends. */
EventWaitHandle
线程阻塞事件 定义如下
EventWaitHandle clearCount = new EventWaitHandle(false, EventResetMode.AutoReset);
using System; using System.Threading; public class Example { // EventWaitHandle 用于演示 // AutoReset 和 ManualReset 同步事件 // private static EventWaitHandle ewh; //一个计数器,用于确保所有线程都已启动并且 //在释放之前被阻止。 A Long用于显示 //使用64位Interlocked方法。 private static long threadCount = 0; // An AutoReset event that allows the main thread to block // until an exiting thread has decremented the count. //阻塞主线程执行,while循环中的 WaitHandle.SignalAndWait(ewh, clearCount);释放ewh,阻塞clearCount private static EventWaitHandle clearCount = new EventWaitHandle(false, EventResetMode.AutoReset); [MTAThread] public static void Main() { // Create an AutoReset EventWaitHandle. // ewh = new EventWaitHandle(false, EventResetMode.AutoReset); // 创建5个线程. 使用 // ParameterizedThreadStart 委托, 能传线程索引参数到start方法 // for (int i = 0; i <= 4; i++) { Thread t = new Thread( new ParameterizedThreadStart(ThreadProc) ); t.Start(i); } //等待所有线程都已启动并阻止。 //当多个线程在32位上使用64位值时 //系统,你必须通过访问该值 //互锁类以保证线程安全。 // while (Interlocked.Read(ref threadCount) < 5) { Thread.Sleep(500); } // Release one thread each time the user presses ENTER, // until all threads have been released. // while (Interlocked.Read(ref threadCount) > 0) { Console.WriteLine("Press ENTER to release a waiting thread."); Console.ReadLine(); // SignalAndWait发出EventWaitHandle信号 //在重置之前正好释放一个线程, //因为它是使用AutoReset模式创建的。 // SignalAndWait然后在clearCount上阻塞。 //再循环之前,允许发出信号的线程减少计数 // WaitHandle.SignalAndWait(ewh, clearCount); } Console.WriteLine(); // 创建一个 ManualReset EventWaitHandle. // ewh = new EventWaitHandle(false, EventResetMode.ManualReset); // Create and start five more numbered threads. // for (int i = 0; i <= 4; i++) { Thread t = new Thread( new ParameterizedThreadStart(ThreadProc) ); t.Start(i); } // Wait until all the threads have started and blocked. // while (Interlocked.Read(ref threadCount) < 5) { Thread.Sleep(500); } //因为EventWaitHandle是 // ManualReset模式创建的, //发出信号释放所有等待线程。 // Console.WriteLine("Press ENTER to release the waiting threads."); Console.ReadLine(); ewh.Set(); } public static void ThreadProc(object data) { int index = (int)data; Console.WriteLine("Thread {0} blocks.", data); // 增加阻塞线程数. Interlocked.Increment(ref threadCount); // 阻塞 ewh.WaitOne(); Console.WriteLine("Thread {0} exits.", data); //减少阻塞线程数 Interlocked.Decrement(ref threadCount); //在发送ewh信号后,主线程阻塞 // clearCount直到发出信号的线程有 //递减计数 立即发信号。 // clearCount.Set(); } }