C++ 单个SetEvent()能否触发多个WaitForSingleObject()呢

C++ 单个SetEvent()能否触发多个WaitForSingleObject()呢,c++,winapi,events,C++,Winapi,Events,这: 似乎不建议 我有三个进程通过管道进行通信。进程A创建一个事件,进程B&C每次使用WaitForSingleObject(在第二个线程中) 现在我们有两个进程,每个进程都在等待一个事件 进程A使用SetEvent()触发事件,进程B响应,进程C不响应 结论: 每个WaitForSingleObject()都需要一个唯一的事件。。。正确吗?使用手动重置事件触发单个事件的多个线程 是使用“手动重置事件”标志的示例您可以使用手动重置事件和PulseEvent函数释放当前等待事件的所有线程 但是,

这:

似乎不建议

我有三个进程通过管道进行通信。进程A创建一个事件,进程B&C每次使用WaitForSingleObject(在第二个线程中)

现在我们有两个进程,每个进程都在等待一个事件

进程A使用SetEvent()触发事件,进程B响应,进程C不响应

结论:


每个WaitForSingleObject()都需要一个唯一的事件。。。正确吗?

使用手动重置事件触发单个事件的多个线程


是使用“手动重置事件”标志的示例

您可以使用手动重置事件和PulseEvent函数释放当前等待事件的所有线程


但是,请注意,这种方法本质上是快速的,因为无法区分哪些是“当前正在等待的线程…”。如果需要唤醒/2等待事件的精确匹配,则应使用更可靠的同步机制。

我希望此示例可以帮助您:

handle1A = CreateEvent(LPSECURITY_ATTRIBUTES, ManualReset, InitialState, NAME)

handle1B = CreateEvent(LPSECURITY_ATTRIBUTES, ManualReset, InitialState, NAME)

handle2A = CreateEvent(LPSECURITY_ATTRIBUTES, ManualReset, InitialState, NAME+GetCurrentThreadId())

handle2B = CreateEvent(LPSECURITY_ATTRIBUTES, ManualReset, InitialState, NAME+GetCurrentThreadId())
A) 如果创建的事件具有相同的
名称
,则每个
设置事件
都会向所有
waitforsingleobjects发出信号

SetEvent(handle1A) // Send signaling to handle1A and handle1B
B) 如果创建具有唯一
名称的事件,则
设置事件
仅向引用的句柄发送信号

SetEvent(handle2) // Send signling only to handle2A. The Id Thread is unique

如果是手动重置事件,则一个事件可以通知多个线程。自动重置事件无法做到这一点。如果多个线程同时等待自动重置事件,并且您将其设置为信号状态,则只有一个线程存在并重置它,而其他线程的行为将未定义。尽管如此,从Microsoft文档中,我们可以假设只有一个线程将退出,而其他线程肯定不会退出。无论如何,我们必须考虑以下引用:“不要假设先进先出(FIFO)顺序。外部事件(如内核模式APCs)可以更改等待顺序”来源-

CreateEvent函数具有bManualReset参数。如果为TRUE,该函数将创建一个手动重置事件对象,这需要使用ResetEvent函数将事件状态设置为无信号。如果此参数为FALSE,该函数将创建一个自动重置事件对象,并且在释放单个等待线程后,系统会自动将事件状态重置为无信号状态,即从WaitForMultipleObjects或WaitForSigleObject之类的函数退出–但是,正如我前面所写的,只有一个线程会收到通知,而不是所有线程

关于PulseEvent,它是不可靠的,永远不应该使用,请参见

只有在调用PulseEvent时处于“等待”状态的线程才会收到PulseEvent的通知。如果它们处于任何其他状态,则不会通知它们,并且您可能永远无法确定线程状态是什么。在同步对象上等待的线程可以通过内核模式异步过程调用暂时从等待状态中移除,然后在APC完成后返回到等待状态。如果对PulseEvent的调用发生在线程已从等待状态移除的时间内,则不会释放该线程,因为PulseEvent仅释放在调用时正在等待的线程。您可以通过以下链接了解有关内核模式异步过程调用(APC)的更多信息:

您可以从以下文章中了解有关自动重置事件和手动重置事件的更多信息:


我没有提到这一点,但我对过程A没有任何控制权,但我将查看PulseEvent函数以供将来参考。。谢谢。如果你可以只更改B&C线程,最好将一个线程从另一个线程唤醒(即A->B->C),而不是试图从A唤醒所有线程。顺便说一句,如果你不控制A,你应该有一些锁定/唤醒协议/接口,并在问题中提及。不要使用PulseEvent,请参阅@CesarB:这可能是真的,但在某些情况下,不唤醒所有线程并不重要。例如,在图像/音频处理情况下,线程正在等待数据。在最坏的情况下,一些线程只会错过一些并不重要的帧。不幸的是,我无法控制进程A,所以我无法实现它。