【发布时间】:2011-08-20 11:42:47
【问题描述】:
我有一个应用程序,其中多个线程等待同一个事件对象发出信号。我看到的问题似乎是一种竞争条件,有时某些线程的等待状态 (WaitForMultipleObjects) 由于事件信号而返回,而其他线程的等待状态显然看不到事件信号,因为它们不要回来。这些事件是使用CreateEvent 作为手动重置事件对象创建的。
我的应用程序处理这些事件,这样当一个事件对象发出信号时,它的“所有者”线程负责重置事件对象的信号状态,如下面的代码 sn-p 所示。等待同一事件的其他线程不会尝试重置其信号状态。
switch ( dwObjectWaitState = ::WaitForMultipleObjects( i, pHandles, FALSE, INFINITE ) )
{
case WAIT_OBJECT_0 + BAS_MESSAGE_READY_EVT_ID:
::ResetEvent( pHandles[BAS_MESSAGE_READY_EVT_ID] );
/* handles the event */
break;
}
换句话说,我看到的问题似乎是Remarks section for PulseEvent on the MSDN website中描述的问题:
如果发生对 PulseEvent 的调用 在线程有的时候 从等待状态中删除, 线程不会被释放,因为 PulseEvent 仅释放那些线程 正在等待的那一刻 叫。因此,PulseEvent 是 不可靠,不应由 新的应用程序。相反,使用 条件变量。
如果发生这种情况,我能看到的唯一解决方案是让每个线程向该对象的所有者线程注册其对给定事件对象的使用,以便所有者线程可以确定何时可以安全地重置事件对象的信号状态。
有没有更好的方法来做到这一点?谢谢。
【问题讨论】:
-
您是否期望在调用 SetEvent 时释放所有线程?按照设计,事件至少释放一个等待线程,除此之外,你不知道还有多少。可能不是全部。
-
@nos:MSDN for SetEvent 说“任何数量的等待线程,或随后通过调用其中一个等待函数为指定事件对象开始等待操作的线程,可以在对象的状态时释放已发出信号。”我将其解读为:如果事件保持设置,最终(双关语不是有意的:))所有等待的线程都会被释放。问题可能是被唤醒的线程重置了事件,所以一些等待的线程被释放而一些没有。
-
@Alexey Kukanov:我相信这正是我遇到的问题。
标签: c++ windows multithreading event-handling