函数PulseEvent()

MSDN上解释如下:

     This function provides a singleoperation that sets to signaled the state of the specified event object andthen resets it to nonsignaled after releasing the appropriate number of waitingthreads.

(这个函数设置特定的事件对象为有信号状态,然后释放相关的等待线程,再置时间对象为无信号状态)但是MSDN又说了,这个函数是不好的,最好不要使用。

对于Event对象,我们知道,分手动重置和自动重置两种。手动重置Event,需要认为控制信号的有无,可以有多个线程等待同一个Event对象,当变成有信号状态时,等待的各个线程都可以被激活。那么对于自动重置事件,激活其中一个线程之后会自动变成无信号状态,几个竞争的线程只能有一个获得激活。

然而,在使用PulseEvent()的时候却发现,等待的线程并不能都被激活,那么,究竟发生了什么呢?

看下面的代码,你是否以为会如你所愿的进行?

   SignalSemaphore(hOtherSemaphore);
    WaitForSingleObject(hEvent, INFINITE);

事实上,这并不总是正确的。因为在信号和等待之间存在竞争,如果在一个线程PluseEvent()的时候,恰好没有线程处于等待状态,那么这个事件将丢失!

这是我在网上搜到的一段话:

    Whilethe thread is sitting waiting for the event, a device driver or part of the kernelitself might ask to borrow the thread to do some processing (by means of a"kernel-mode APC"). During that time, the thread is not in the wait state. (It's beingused by the device driver.) If the PulseEvent happens while thethread is being "borrowed", then it will not be woken from the wait, becausethe PulseEvent functionwakes only threads that were waiting atthe time the PulseEvent occurs.

很好的解释了这种现象的原因,原来一个线程处于等待状态的过程中,会有一些瞬间其状态并不为等待状态。这就造成PulseEvent()不能激活应该被激活的等待线程。

这些瞬间包括什么呢?比如发生了系统调用,缺页中断,硬件中断......等等。

怎么解决这个问题呢?MSDN建议使用SiginalObjectAndWait()。具体信息可以查询MSDN.

PulseEvent在某些场合还是比较有用的,比如创建的事件是有名的,并且是手动设置的,同时有多个线程都在等待同一事件。那么这个时候就需要用到pulseEvent了。

如果用setevent 是不行的,因为一旦事件被信号,你不知道什么时候该reset它,因为你不知道多个线程什么时候能都处理完。当然你会说用自动的,但是自动的事件被信号之后一旦有一个线程捕获到它就会被去信号,导致别的线程捕获不到该事件。


你可能感兴趣的:(event,Pulse)