Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么';SignalObjectAndWait的用途是什么?是否存在SetEvent和WaitForSingleObject?_C++_Windows_Multithreading_Winapi_Multiprocessing - Fatal编程技术网

C++ 什么';SignalObjectAndWait的用途是什么?是否存在SetEvent和WaitForSingleObject?

C++ 什么';SignalObjectAndWait的用途是什么?是否存在SetEvent和WaitForSingleObject?,c++,windows,multithreading,winapi,multiprocessing,C++,Windows,Multithreading,Winapi,Multiprocessing,我刚刚意识到Windows平台有API函数。但现在已经有了。您可以将它们结合使用以实现与SignalObjectAndWait相同的目标 基于此,SignalObjectAndWait比单独调用SetEvent和WaitForSingleObject更有效。它还指出: 线程可以使用SignalObjectAndWait函数来确保工作线程在向对象发送信号之前处于等待状态 我不完全理解这句话,但效率似乎不是我们需要SignalObjectAndWait的唯一原因。任何人都可以提供这样一种场景:Set

我刚刚意识到Windows平台有API函数。但现在已经有了。您可以将它们结合使用以实现与
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实现的,不需要其他函数

  • 为所有作业线程创建一个通用的自动重置事件,以表示有一个(多个)任务可用;还可以创建每个线程自动重置事件,每个作业线程一个事件
  • 多个作业执行,一旦完成所有作业的运行,所有作业都将使用WaitForMultipleObjects等待此常见的自动重置“任务可用”事件-它将等待两个事件-常见事件和自己的线程事件
  • 调度程序线程将新的(挂起的)作业放入列表
  • 作业列表访问必须受到EnterCriticalSection/LeaveCriticalSection的保护,因此没有人以其他方式访问此列表
  • 每个作业线程在完成一个作业后,在开始等待自动重置“任务可用”事件及其自身事件之前,都会检查挂起的作业列表。如果列表不是空的,则从列表中获取一个作业(将其从列表中删除)并执行它
  • 必须有另一个受关键部分保护的列表–等待作业线程列表
  • 在每个作业开始等待之前,即在调用WaitForMultipleObjects之前,它将自己添加到“等待”列表中。退出等待时,它会将自己从等待列表中移除
  • 当调度程序线程将新的(挂起的)作业放入作业列表时,它首先进入作业列表的关键部分,然后进入踏板列表的关键部分-因此同时进入两个关键部分。然而,作业线程可能永远不会同时进入两个关键部分
  • 如果只有一个作业挂起,调度程序将公共自动重置事件设置为信号状态(call SetEvent)——不管哪个休眠作业线程将拾取该作业
  • 如果有两个或多个作业挂起,它将不会发出公共事件的信号,但会计算有多少线程正在等待。如果没有
    dwRet = WaitForSingleObject(hEventWorkerDone, INFINITE);
    if( WAIT_OBJECT_0 == dwRet)
      SetEvent(hEventMoreWorkToDo);
    
    dwRet = SignalObjectAndWait(hEventWorkerDone,
                                hEventMoreWorkToDo,
                                INFINITE, 
                                FALSE);