AutoResetEvent是EventWaitHandle的一个简单包装,内部没有额外的任何逻辑。它最大的特点就是,调用了Set方法将事件设为true之后,其中一个等待线程得到执行后,它会自动调用Reset方法,将事件信号设为false,以阻塞其它的线程。相当于放一个线程进来,门自动就关了(自动门)。
例子,使用AutoResetEvent实现一个简单的线程同步锁。
1 private class SimpleWaitLock : IDisposable 2 { 3 //初始化一定要是true,否则,第一个调用Enter方法的线程会被阻塞 4 private AutoResetEvent m_autoResetEvent = new AutoResetEvent(true); 5 6 7 public void Enter() 8 { 9 //第一个线程调用这个方法后,事件将会为false,其他线程会被阻塞 10 m_autoResetEvent.WaitOne(); 11 Console.WriteLine("Thread {0} Enter;",Thread.CurrentThread.Name); 12 Thread.Sleep(100); 13 Exit(); 14 } 15 public void Exit() 16 { 17 Console.WriteLine("Thread {0} Exit;", Thread.CurrentThread.Name); 18 m_autoResetEvent.Set(); 19 20 } 21 public void Dispose() 22 { 23 m_autoResetEvent.Dispose(); 24 Console.WriteLine("Thread {0} dispose;", Thread.CurrentThread.Name); 25 } 26 } 27 static void Main() 28 { 29 SimpleWaitLock slock = new SimpleWaitLock(); 30 for (int i = 0; i < 10; i++) 31 { 32 Thread thread = new Thread(slock.Enter); 33 thread.Name = "thread" + i.ToString(); 34 thread.Start(); 35 } 36 Console.Read(); 37 } 38 39 40 }
执行结果:
ManualResetEvent
ManualResetEvent是EventWaitHandle的一个简单包装,内部也没有额外的任何逻辑。它和AutoResetEvent唯一的不同是,调用了Set方法将事件设为true后,不会去调用Reset方法,这将导致事件一直处于true,其它等待的多个线程都会得到执行,直到你手动调用Reset方法。相当于你把门打开后,需要手动去关(非自动门)。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 private class SimpleWaitLock : IDisposable 2 { 3 //初始化一定要是true,否则,第一个调用Enter方法的线程会被阻塞 4 private ManualResetEvent m_mannualResetEvent = new ManualResetEvent(false); 5 6 7 public void Enter() 8 { 9 //第一个线程调用这个方法后,事件将会为false,其他线程会被阻塞 10 m_mannualResetEvent.WaitOne(); 11 Console.WriteLine("Thread {0} Enter;",Thread.CurrentThread.Name); 12 Thread.Sleep(100); 13 14 } 15 public void Exit() 16 { 17 //Console.WriteLine("Thread {0} Exit;", Thread.CurrentThread.Name); 18 m_mannualResetEvent.Set(); 19 20 } 21 public void Dispose() 22 { 23 m_mannualResetEvent.Dispose(); 24 Console.WriteLine("Thread {0} dispose;", Thread.CurrentThread.Name); 25 } 26 } 27 static void Main() 28 { 29 SimpleWaitLock slock = new SimpleWaitLock(); 30 for (int i = 0; i < 10; i++) 31 { 32 Thread thread = new Thread(slock.Enter); 33 thread.Name = "thread" + i.ToString(); 34 thread.Start(); 35 } 36 Thread.Sleep(1000); 37 Console.WriteLine("The door is open, all threads can go over..."); 38 slock.Exit(); 39 Console.Read(); 40 } 41 42 43 }
执行结果如下:
总结:
1、看起来,ManualResetEvent更加自由、开放。如果把AutoResetEvent看作是只能单人通过的独木桥的话,那么ManualResetEvent就像一座城门,一下子可以涌入千军万马,当然你也可以随时关闭城门,让后面的人进不来。
2、AutoResetEvent.Set() = ManualResetEvent.Set() + ManualResetEvent.Reset();
3、如果共享资源仅允许一个线程单独使用的情况下,可以选择AutoResetEvent;如果共享资源允许多个线程同时使用,则可以选择ManualResetEvent。
4、如果要控制多个线程暂停、继续,可以选择ManualResetEvent。
5。而Semaphore可实现多并发同步控制