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(); } }
相关推荐
总结,`AutoResetEvent`是C#中用于线程同步和异步控制的重要工具,它帮助开发者有效地管理线程间的交互,实现线程交替或跟随执行。在实际开发中,灵活运用这些概念和技术,可以提高程序的效率和并发性能。
在多线程编程中,`AutoResetEvent` 和 `ManualResetEvent` 是两种重要的同步原语,用于控制线程间的协作和同步。本压缩包文件提供了关于这两种事件类型的实例代码,帮助开发者理解它们的工作原理和用法。 首先,让...
引入命名空间: using System.Threading; AutoResetEvent: autoResetEvent.WaitOne();//运行完后,**自动将事件...ManualResetEvent: manulResetEvent.WaitOne();//运行完后,**不会自动将事件状态设置为无信号**
然而,多线程也带来了一定的复杂性,特别是在资源竞争和线程间协调方面。`ManualResetEvent`是.NET Framework提供的一种线程同步原语,用于控制线程的执行顺序和互斥访问,确保程序的正确性和一致性。 `...
- 分析和理解线程间的交互,确保没有竞态条件或死锁。 - 使用适当的同步机制,避免过度同步,提高性能。 - 注释清晰,特别是在不确定的地方,便于其他开发者理解和改进代码。 在提供的"multiThreading"文件夹中,...
- **信号量(ManualResetEvent, AutoResetEvent)**:用于线程间的同步,等待事件发生后才继续执行。 - **条件变量(Monitor.Wait, Monitor.Pulse)**:允许线程等待特定条件满足后才继续执行。 9. **线程状态** ...
- **事件(Events)**:通过WaitHandle类的子类(如ManualResetEvent或AutoResetEvent)来同步线程,一个线程等待特定事件发生,另一个线程触发事件。 - **条件变量(Conditional Variables)**:允许线程在满足...
在多线程编程中,`ManualResetEvent`是.NET Framework提供的一种同步原语,它用于控制线程间的通信和同步。这个类属于`System.Threading`命名空间,是`WaitHandle`的一个子类,用于创建一个可以手动重置的事件信号,...
总结来说,ManualResetEvent是.NET平台下实现线程同步的重要工具,通过其Set、Reset和WaitOne方法,我们可以精确控制线程的执行流程。了解并熟练运用这些方法,对于编写高效、稳定的多线程程序至关重要。同时,正确...
5. **线程同步对象**:如`Mutex`, `Monitor`, `AutoResetEvent`, `ManualResetEvent`等,用于控制线程之间的访问和通信。 6. **线程状态管理**:了解`ThreadState`枚举,如`Running`, `Stopped`, `Aborted`等,以便...
有两类EventWaitHandle:AutoResetEvent和ManualResetEvent。AutoResetEvent在事件触发后自动重置,只有一个等待的线程可以继续执行;而ManualResetEvent则需要手动调用Reset() 方法来重置事件状态,因此可以唤醒多...
可以使用Monitor类的`Pulse()`和`Wait()`方法,或者使用ManualResetEvent和AutoResetEvent等事件对象。例如,一个线程可能需要等待另一个线程发出信号才能继续执行: ```csharp ManualResetEvent doneEvent = new ...
同时,可以使用Thread的Sleep方法使线程在没有消息时进入等待状态,或者使用ManualResetEvent或AutoResetEvent来控制线程的启动和停止。 标签“c#”、“vb.net”表明这是两种.NET语言的实现,虽然语法和一些特性...
3.1 WaitOne/SignalOne:ManualResetEvent和AutoResetEvent用于线程间的等待和通知。 3.2 CountdownEvent:计数事件,当计数值减至零时,所有等待的线程被释放。 3.3 Barrier:屏障,使多个线程到达某一点后同时继续...
4. **WaitHandle.WaitOne() 和 WaitHandle.WaitAny():** 这两个方法允许线程等待一个或多个`WaitHandle`对象(如`ManualResetEvent`和`AutoResetEvent`)变为信号状态。在线程中,可以使用`WaitOne()`来阻塞线程,...
例如,`AutoResetEvent`和`ManualResetEvent`可以作为线程间的等待信号: ```csharp AutoResetEvent eventWaitHandle = new AutoResetEvent(false); // 等待信号 eventWaitHandle.WaitOne(); // 释放信号 ...
通过合理利用`ManualResetEvent`的状态转换,开发者可以构建复杂而高效的多线程应用程序,实现对资源的精确控制和线程的有序执行。然而,由于涉及线程的阻塞与唤醒,使用时需谨慎,避免死锁和资源浪费。
- 静态成员、锁和线程局部存储(`ThreadLocal<T>`)是实现线程安全的方法。 - 避免共享状态和使用不可变对象可以减少线程安全问题。 7. **线程优先级** - 操作系统为每个线程分配优先级,但并不保证优先级高的...