C++ 在多个自动重置事件上使用WaitForMultipleObjects

C++ 在多个自动重置事件上使用WaitForMultipleObjects,c++,windows,multithreading,winapi,C++,Windows,Multithreading,Winapi,在我的一个项目中,我创建了多个自动重置事件和两个线程,这些线程使用WaitForMultipleObjects在继续运行之前等待一些事件,如: HANDLE hTerminateEvent = CreateEvent(...); // auto reset HANDLE hStateChangedEvent = CreateEvent(...); // auto reset void thread1Func() { HANDLE handles[2] = { hTerminate

在我的一个项目中,我创建了多个自动重置事件和两个线程,这些线程使用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重置为无信号的


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

您可以使用信号量而不是事件,使用ReleaseSemaphore并传入等于线程数的计数。

您可以使用信号量而不是事件,使用ReleaseSamphore并传入等于线程数的计数。

如果希望两个线程都对hTerminateEvent作出反应,则必须将其设置为手动重置。假设您正在使用它作为一个信号来告诉多个线程终止它们自己,所以无论如何将它设置为自动重置是没有意义的。与hStateChangedEvent相同

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

b手动复位[in]

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

当手动重置事件对象的状态发出信号时,它将保持信号状态,直到ResetEvent函数将其显式重置为非信号状态。在通知对象的状态时,可以释放任意数量的等待线程,或随后开始对指定事件对象执行等待操作的线程

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


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

如果您希望两个线程都对hTerminateEvent作出反应,则必须将其设置为手动重置。假设您正在使用它作为一个信号来告诉多个线程终止它们自己,所以无论如何将它设置为自动重置是没有意义的。与hStateChangedEvent相同

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

b手动复位[in]

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

当手动重置事件对象的状态发出信号时,它将保持信号状态,直到ResetEvent函数将其显式重置为非信号状态。在通知对象的状态时,可以释放任意数量的等待线程,或随后开始对指定事件对象执行等待操作的线程

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


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

名为terminate的事件应始终为MRE。名为terminate的事件应始终为MRE。