多线程 -Synchronization Events and Wait Handles
多线程之间不能相互通信,为了达到这个目的。我们借助两个同步事件类:AutoResetEvent和ManualResetEvent。这两个类的功能是一样的,使用的唯一不同是前者调用Set()方法后,自动的调用Reset(),而后者不会。至于这里的Set()和ReSet() 的作用是什么,先放放,待会再说。因为想弄明白他们的作用之前我们必须要先明白另外的两个词:signaled,unsignaled
1. signaled,unsignaled
signaled :有信号的,表明收到了同步事件(AutoResetEvent和ManualResetEvent)的信号,通知被暂停(suspended )的线程可以继续执行了
unsignaled:没有信号的,同步事件没有收到信号,暂停的线程则继续等待。
我们可以把signal理解成中文“通知”,例如:
你和另外的一个人合作手工制作一辆组装自行车,你们分工,一个人做前轮,另外一个做后轮。很明显,你们没有必要一个人先做,另外一个人等着别人做好他再开始。所以你们一起开工(2个Thread同时start)。你做好了,并不能就立刻进行下一步组装,因为才一个轮子(一个Thread完成了),必须两个轮子都好了才能开始,所以你必须等你的同伴。反之亦然。
但是呢你们两个都在各自的家里做,都并不知道对方的进度状态 (因为线程之间并不能直接通过彼此传递信息来通信),可是你们又必须把两个轮子组合起来变成自行车。所以你们必须有中有效的机制来解决这个问题。于是就有了 AutoResetEvent和ManualResetEvent。
2. AutoResetEvent和ManualResetEvent :
他们的作用就像个大喇叭,他们可以通过广播来播送信息,AutoResetEvent和ManualResetEvent则是通过调用 WaitOne(WaitAll(),waitany())和Set()两个方法来告诉所有拥有他们的线程发送信号:WaitOne()是对线程说,等你运行到这个地方,给我停下来,至于什么时候你可以继续前进,等候上面通知(什么时候调用了Set())。当ResetEvent调用了Set后,暂停的线程被唤醒便继续往下运行了。
ResetEvent 有两个状态,UnSignaled,signaled,在他们调用Wait 和Set的时候发生切换。说道状态切换,这里可以指出AutoResetEvent和Manuresetevent之间的唯一的一点区别了。
AutoResetEvent autoEvent=new AutoResetEvent(false);
//false的话,初始状态就是阻止线程继续运行,当autoEvent.WaitOne()阻止线程的继续运行。一般都是设置阻止。
//如果是true, 就不会阻止了
autoEvent.WaitOne();// autoEvent的状态由
Console.WriteLine("Main thread is going on..."));
这里只有只有t1的线程完成后,通过Set()了,其他线程(这里是Main线程)才会继续运行
autoEnvet然后继续 Wait,再启动一个i额线程t2
Thread t2 = new Thread(DoWork);
autoEvent.WaitOne();// autoEvent的状态由
这时候运行并不会出乎你的意外,正常运行。
但是如果 autoEvent 不是AutoResetEvent,而是一个ManuResetEvent,t2调用Dowork时候,你会发现Main线程不睬autoEvent.WaitOne()了,自己不等待直接先执行了。因为 autoEvent 这个时候的状态仍然是Signaled,即使你调用了waitOne(),它仍然不阻止,而是让任意多的线程一直是处于激活状态,除非你调用了Reset方法。
代码改成
autoEvent.Reset();//to reset initial state ,from signaled to unsignaled
Thread t2 = new Thread(DoWork);
autoEvent.WaitOne();// autoEvent的状态由
于是你可能会觉得ManualResetEvent多了一条代码,岂不是很麻烦吗?是有点,但是存在即是合理的。ManualResetEvent的好处是它Set一次后,可以激活任意多个Thread,不要像AutoResetEvent的每次都自动的给你Reset一下,尽管也很快,还是消耗一点性能,哪怕那只是一丁点,可是如果很多个线程呢?
3.Set 和Wait
Set倒是没有多少说的。Wait有点讲究,因为有些线程跑的块,有些跑的慢,那些特别快的线程有时候不愿意一直傻等那些慢线程,就像兔子真的是无法和乌龟共同赶路的一样。于是在event.wait的时候,我们可以设置个timeout时间
autoEvent.WaitOne(milliSeconds);
这样,那些快线程等了1000毫秒后就可以闪人了。
浙公网安备 33010602011771号