分类: C#/.net
2014-08-16 22:46:15
两者都继承自EventWaitHandle,自然也就有点相通的地方了
简单来说,无论是AutoResetEvent还是ManualResetEvent,都是通过发出Signal信号来通知正在等待的线程的。有人可能要问,为什么要用它们来做这些事情, 嗯, 是这样的, 在.Net的多线程环境中,资源的共享变得尤其重要,如果没有一个有效的方法来维护资源的原子状态,在抢占式的CPU环境中,所有的事情都会变得无法控制。AutoResetEvent和ManualResetEvent正是用来保证资源的原子性的一个手段的两个方面。正如它们的名字一样, AutoResetEvent会在每次被Signal了之后自动(Automatically)转变为UnSignal,而ManualResetEvent则不然,无论是Signal还是UnSignal都需要人为的介入去改变它的状态。
在AutoResetEvent的构造函数中,有唯一的一个参数,initialState,Boolean类型,它用来初始化AutoResetEvent的Signal状态,True为Signal,False为UnSignal,这与ManualResetEvent的构造函数是一样的。
AutoResetEvent或ManualResetEvent都是通过Set()/Reset()两个方法来Signal/UnSignal信号,通过调用WaitOne方法来阻塞当前线程,当收到Signal后就继续往下执行。上面提到过,AutoResetEvent会自动把信号复位(自动调用Reset),而ManualResetEvent则需要人手复位,也就是说,AutoResetEvent每次只允许一条线程进入,其它所有需要访问该资源的线程都要排队等候,直到AutoResetEvent得到信号后,下一条线程开始工作,同时AutoResetEvent又会自动复位信号,让其他线程继续等候;而ManualResetEvent则每次可以唤醒多个线程,因为当ManualResetEvent得到信号后,其他调用WaitOne方法的线程都将得到信号得以继续往下执行,ManualResetEvent不会自动复位信号,换句话说,除非手动的调用了ManualResetEvent.Reset方法,否则ManualResetEvent一直保持有信号状态,这样就可以同时唤醒多条线程了
作为一个示例,下面的DemoCode一开始就运行一条子线程,然后用AutoResetEvent/ManualResetEvent来控制MessageBox的输出流程。
如果在Foo和button1_Click里面用AutoResetEvent,一开始得到"1",然后每点击一次Button1得到"2"和"3"。
如果用ManualResetEvent,一开始得到"1",然后只需点击Button1一次,就可以得到"2"和"3"了