在我的一个项目中,我创建了多个auto reset events
和两个线程,线程使用WaitForMultipleObjects
在继续运行之前等待某些事件,如:
HANDLE hTerminateEvent = CreateEvent(...); // auto reset
HANDLE hStateChangedEvent = CreateEvent(...); // auto reset
void thread1Func()
{
HANDLE handles[2] = { hTerminateEvent, hStateChangedEvent };
WaitForMultipleObjects(2, handles, FALSE/*bWaitAll*/, INFINITE);
...
}
void thread2Func()
{
HANDLE handles[2] = { hTerminateEvent, hStateChangedEvent };
WaitForMultipleObjects(2, handles, FALSE/*bWaitAll*/, INFINITE);
...
}
我之前认为,一旦hTerminateEvent
单挑,两个线程都会被唤醒,但似乎对于自动重置事件不是这样,一个人被唤醒是随机的,并且在一个唤醒之后,它重置hTerminateEvent
无信令。
我的问题是如何解决这个问题:使用手动重置事件?还是有任何设计来解决这个问题?谢谢!
答案 0 :(得分:3)
如果您希望两个线程都对hTerminateEvent
作出反应,则必须将其设置为手动重置。大概你用它作为一个信号告诉多个线程自己终止,所以无论如何将它设置为自动复位是没有意义的。与hStateChangedEvent
相同。
如果您阅读了CreateEvent()
文档,则会说:
bManualReset [in]
如果此参数为TRUE,则该函数会创建一个手动重置事件对象,该对象需要使用ResetEvent函数将事件状态设置为无信号。如果此参数为FALSE,则该函数会创建一个自动重置事件对象,并且系统会在释放一个等待线程后自动将事件状态重置为无信号。
...
当发出手动重置事件对象的状态时,会一直发出信号,直到它被ResetEvent函数显式重置为无信号。当对象的状态发出信号时,可以释放任意数量的等待线程或随后开始对指定事件对象执行等待操作的线程。
当发出自动重置事件对象的状态时,会一直发出信号,直到释放一个等待的线程为止;然后系统自动将状态重置为无信号。如果没有线程在等待,则事件对象的状态仍然会发出信号。
因此,当使用自动重置事件时,您无法唤醒同时等待它的多个线程。
答案 1 :(得分:1)
您可以使用信号量而不是事件,并使用ReleaseSemaphore()并传入等于线程数的计数。