C++ 什么';SignalObjectAndWait的用途是什么?是否存在SetEvent和WaitForSingleObject?
我刚刚意识到Windows平台有API函数。但现在已经有了。您可以将它们结合使用以实现与C++ 什么';SignalObjectAndWait的用途是什么?是否存在SetEvent和WaitForSingleObject?,c++,windows,multithreading,winapi,multiprocessing,C++,Windows,Multithreading,Winapi,Multiprocessing,我刚刚意识到Windows平台有API函数。但现在已经有了。您可以将它们结合使用以实现与SignalObjectAndWait相同的目标 基于此,SignalObjectAndWait比单独调用SetEvent和WaitForSingleObject更有效。它还指出: 线程可以使用SignalObjectAndWait函数来确保工作线程在向对象发送信号之前处于等待状态 我不完全理解这句话,但效率似乎不是我们需要SignalObjectAndWait的唯一原因。任何人都可以提供这样一种场景:Set
SignalObjectAndWait
相同的目标
基于此,SignalObjectAndWait
比单独调用SetEvent
和WaitForSingleObject
更有效。它还指出:
线程可以使用SignalObjectAndWait
函数来确保工作线程在向对象发送信号之前处于等待状态
我不完全理解这句话,但效率似乎不是我们需要
SignalObjectAndWait
的唯一原因。任何人都可以提供这样一种场景:SetEvent
+WaitForSingleObject
无法提供SignalObjectAndWait
提供的功能?正如MSDN所解释的,目的是确保线程在发出事件信号之前处于等待状态。如果调用WaitForSingleObject,线程将处于waitstate状态,但在调用SetEvent之前不能调用该状态,因为这将导致SetEvent仅在等待完成后发生-如果没有其他调用SetEvent,这是毫无意义的 我的理解是,这个单一功能更有效,因为它避免了以下情况
与单独的函数调用(如SetEvent
后接WaitForSingleObject
)相比,SignalObjectAndWait
函数提供了一种更有效的方法来向一个对象发送信号,然后再等待另一个对象
当您SetEvent
而另一个[esp.higher priority]线程正在等待此事件时,可能会发生线程调度程序从信令线程夺走控制权的情况。当线程接收回控制时,它只执行以下WaitForSingleObject
调用,从而浪费了上下文切换时间
使用
SignalObjectAndWait
你可以提示内核说“嘿,我无论如何都会等待另一个事件,所以如果它对你有任何影响,你就不会在上下文切换时过度反弹。”如你所知,Microsoft给出了以下示例,说明了如果我们已经需要单独的SetEvent和WaitForSingleObject,为什么我们可能需要SignalObjectAndWait(引用Microsoft示例):
线程可以使用SignalObjectAndWait函数来确保工作线程在向对象发送信号之前处于等待状态。例如,线程和工作线程可以使用事件对象的句柄来同步其工作。线程执行如下代码:
工作线程执行以下代码:
此算法流有缺陷,不应使用。我们不需要这样一种复杂的机制,即线程相互通知,直到我们处于“竞争状态”。在本例中,Microsoft本身创建竞争条件。工作线程只需等待事件并从列表中获取任务,而生成任务的线程只需将任务添加到此列表并发出事件信号。因此,我们只需要一个事件,而不是上面的Microsoft示例中的两个事件。该列表必须受到关键部分的保护。生成任务的线程不应等待工作线程完成任务。如果有任务需要在完成时通知某人,则任务应自行发送通知。换句话说,是任务在完成时通知线程——不是线程专门等待作业线程直到它完成所有任务
这种有缺陷的设计,如微软的例子,为诸如原子信号对象和等待以及原子脉冲事件这样的怪物创造了必要条件,而这些功能最终导致了毁灭
这里有一个算法,你如何实现你在问题中设定的目标。这一目标是通过简单事件、简单函数SetEvent和WaitForSingleObject实现的,不需要其他函数
dwRet = WaitForSingleObject(hEventWorkerDone, INFINITE);
if( WAIT_OBJECT_0 == dwRet)
SetEvent(hEventMoreWorkToDo);
dwRet = SignalObjectAndWait(hEventWorkerDone,
hEventMoreWorkToDo,
INFINITE,
FALSE);