1

在我的一个项目中,我创建了多个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为未发出信号。

我的问题是如何解决这个问题:通过使用手动重置事件?或者是否有任何设计可以解决这个问题?谢谢!

4

2 回答 2

3

如果您希望两个线程都做出反应,hTerminateEvent则必须将其设置为手动重置。大概您将它用作告诉多个线程自行终止的信号,因此无论如何将其设置为自动重置是没有意义的。与 相同hStateChangedEvent

如果您阅读CreateEvent()文档,它会说:

bManualReset [in]

如果此参数为 TRUE,则该函数创建一个手动重置事件对象,该对象需要使用 ResetEvent 函数将事件状态设置为无信号。如果此参数为 FALSE,则该函数创建一个自动重置事件对象,系统会在释放单个等待线程后自动将事件状态重置为 nonsignaled

...

手动重置事件对象的状态发出信号时,它会一直保持信号状态,直到它被 ResetEvent 函数显式重置为非信号状态。任何数量的等待线程,或随后开始为指定事件对象等待操作的线程,都可以在对象状态发出信号时被释放

自动重置事件对象的状态发出信号时,它会保持信号状态,直到释放单个等待线程;然后系统自动将状态重置为 nonsignaled。如果没有线程在等待,则事件对象的状态保持信号状态。

因此,当使用自动重置事件时,您无法唤醒同时等待它的多个线程。

于 2012-12-12T02:59:12.123 回答
1

您可以使用信号量代替事件,并使用 ReleaseSemaphore() 并传入等于线程数的计数。

于 2012-12-12T02:42:55.193 回答