苏州专业网站制作方案,受欢迎的徐州网站建设,wordpress简洁企业主题,企业vi设计模板注意#xff1a;当WaitForMultipleObjects等待多个内核对象的时候#xff0c;如果它的bWaitAll 参数设置为false。其返回值减去WAIT_OBJECT_0 就是参数lpHandles数组的序号。如果同时有多个内核对象被触发#xff0c;这个函数返回的只是其中序号最小的那个。
如果bWaitAll …注意当WaitForMultipleObjects等待多个内核对象的时候如果它的bWaitAll 参数设置为false。其返回值减去WAIT_OBJECT_0 就是参数lpHandles数组的序号。如果同时有多个内核对象被触发这个函数返回的只是其中序号最小的那个。
如果bWaitAll 为TRUE 则等待所有信号量有效在往下执行。FALSE 当有其中一个信号量有效时就向下执行
问题就在这里我们如何可以获取所有被同时触发的内核对象。
举个例子我们需要在一个线程中处理从完成端口、数据库、和可等待定时器来的数据。一个典型的实现方法就是用WaitForMultipleObjects等待所有的这些事件。如果完成端口数据库发过来的数据量非常大可等待定时器时间也只有几十毫秒。那么这些事件同时触发的几率可以说非常大我们不希望丢弃任何一个被触发的事件。那么如何能高效地实现这一处理呢
MSDN中有一句非常重要的描述它可以说是WaitForMultipleObjects用法的精髓The function modifies the state of some types of synchronization objects. Modification occurs only for the object or objects whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one. When bWaitAll is FALSE, and multiple objects are in the signaled state, the function chooses one of the objects to satisfy the wait; the states of the objects not selected are unaffected.
多个内核对象被触发时WaitForMultipleObjects选择其中序号最小的返回。而WaitForMultipleObjects它只会改变使它返回的那个内核对象的状态。
这儿又会产生一个问题如果序号最小的那个对象频繁被触发那么序号比它大的内核对象将得不到被处理的机会。为了解决这一问题可以采用双WaitForMultipleObjects检测机制来实现。见下面的例子
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{ DWORD dwRet 0; int nIndex 0; while(1) { dwRet WaitForMultipleObjects(nCount,pHandles,false,INFINITE); switch(dwRet) {case WAIT_TIMEOUT: break; case WAIT_FAILED: return 1;default:{nIndex dwRet - WAIT_OBJECT_0; ProcessHanlde(nIndex); //同时检测其他的事件 while(nIndex nCount) //nCount事件对象总数 { dwRet WaitForMultipleObjects(nCount - nIndex,pHandles[nIndex],false,0); switch(dwRet) {case WAIT_TIMEOUT: nIndex nCount; //退出检测,因为没有被触发的对象了. break;case WAIT_FAILED: return 1; default:{nIndex dwRet - WAIT_OBJECT_0; ProcessHanlde(nIndex); }break;}//switch结束}//while结束}//default结束break;}//switch结束}//while结束return 0;
} SignalObjectAndWait()
你也可以同时通知一个内核对象同时等待另一个内核对象这两个操作以原子的方式进行。 语法
DWORD SignalObjectAndWait(HANDLE hObjectToSignal,//通知的内核对象HANDLE hObjectToWaitOn,//等待的内核对象DWORD dwMilliseconds,//等待的时间BOOL bAlertable//与IO完成端口有关的参数暂不讨论
);
参数
hObjectToSignal 要发信号的对象的句柄。此对象可以是信号量互斥量或事件。 如果句柄是信号量则需要SEMAPHORE_MODIFY_STATE访问权限。如果句柄是事件则需要EVENT_MODIFY_STATE访问权限。如果句柄是互斥锁且调用者不拥有互斥锁则函数将失败并显示ERROR_NOT_OWNER。hObjectToWaitOn 要等待的对象的句柄。该SYNCHRONIZE访问权是必需的; 有关更多信息请参阅同步对象安全性和访问权限 。有关可以指定其句柄的对象类型的列表请参阅“备注”部分。dwMilliseconds 超时间隔以毫秒为单位。即使对象的状态是非信号且没有完成或异步过程调用APC对象排队该函数也会在间隔过去时返回。如果dwMilliseconds为零则该函数测试对象的状态检查排队的完成例程或APC并立即返回。如果dwMilliseconds是INFINITE则函数的超时间隔永远不会过去。bAlertable 如果此参数为TRUE则该函数在系统对I / O完成例程或APC函数进行排队时返回并且该线程调用该函数。如果为FALSE则函数不返回并且线程不调用完成例程或APC函数。 当排队APC的函数调用完成时完成例程排队。只有当bAlertable为TRUE且调用线程是排队APC的线程时此函数才会返回并调用完成例程。
返回值
返回代码/值描述WAIT_ABANDONED/0x00000080L指定的对象是在拥有线程终止之前由拥有互斥对象的线程未释放的互斥对象。互斥对象的所有权被授予调用线程并且互斥锁被设置为无信号。如果互斥锁正在保护持久状态信息则应检查它是否一致。WAIT_IO_COMPLETION/0x000000C0L等待由一个或多个排队到线程的用户模式 异步过程调用APC结束。WAIT_OBJECT_0/0x00000000L发出指定对象的状态信号。WAIT_TIMEOUT/0x00000102L超时间隔已过对象的状态未发出信号。WAIT_FAILED/(DWORD)0xFFFFFFFF该功能失败了。要获取扩展错误信息请调用 GetLastError。
备注 所述SignalObjectAndWait功能提供了一个更有效的方式来信号发送一个对象然后在另一等待相比单独的函数调用诸如 SetEvent的随后WaitForSingleObject的。
该 SignalObjectAndWait函数可以等待以下对象
更改通知控制台输入事件内存资源通知互斥处理信号线
线程可以使用SignalObjectAndWait函数来确保工作线程在发信号通知对象之前处于等待状态。例如线程和工作线程可以使用句柄来事件对象来同步它们的工作。该线程执行如下代码 dwRet WaitForSingleObject(hEventWorkerDone, INFINITE);if( WAIT_OBJECT_0 dwRet)SetEvent(hEventMoreWorkToDo);
工作线程执行如下代码
dwRet SignalObjectAndWait(hEventWorkerDone,hEventMoreWorkToDo,INFINITE, FALSE);
注意“信号”和“等待”不能保证作为原子操作执行。在调用SignalObjectAndWait的线程开始等待第二个对象之前在其他处理器上执行的线程可以观察第一个对象的信号状态。
在Windows 7中使用SignalObjectAndWait 和PulseEvent时要格外小心 因为在多个线程之间使用这些API会导致应用程序死锁。由信号发送线程SignalObjectAndWait 调用PulseEvent以发信号通知的等待对象SignalObjectAndWait呼叫。在某些情况下SignalObjectAndWait的调用者无法及时接收等待对象的信号状态从而导致死锁。
使用等待函数和直接或间接创建窗口的代码时要小心。如果一个线程创建了任何窗口它必须处理消息。消息广播将发送到系统中的所有窗口。使用没有超时间隔的等待函数的线程可能会导致系统死锁。间接创建窗口的两个代码示例是DDE和COM CoInitialize。因此如果您有一个创建窗口的线程请务必从另一个线程调用SignalObjectAndWait。如果无法做到这一点可以使用 MsgWaitForMultipleObjects或 MsgWaitForMultipleObjectsEx但功能不相同。
要编译使用此函数的应用程序请将 _WIN32_WINNT 定义为0x0400或更高版本。