Waiting for Multiple Objects
在Windows中, WaitForMultipleObjects函數(shù)是一種同步的方法,原形定義如下:
DWORD WinApi WaitForMultipleObjects(
DWORD nCount, const Handle * lpHandles, BOOL bWaitAll, DWORD dwMilliseconds );
調(diào)用該函數(shù)的線程進(jìn)入等待狀態(tài),直到條件滿足時繼續(xù)執(zhí)行,條件的滿足和參數(shù)有關(guān).
第一個參數(shù)為要等待的Objects的個數(shù),通常這些Objects是一組句柄(Handles),可以是內(nèi)核對象句柄或者是非內(nèi)核對象
句柄,這一組句柄由第2個指向分配給一系列句柄緩沖區(qū)的指針指出,第3個參數(shù)如果為TRUE,則等待的線程必須等到所有
句柄全部完成執(zhí)行后才繼續(xù)執(zhí)行,如果為FALSE, 那么只要有一個返回即可繼續(xù)執(zhí)行,第4個參數(shù)設(shè)置TIMEOUT的時間,
如果在給定的dwMilliseconds內(nèi)仍沒等到條件滿足則返回.
那么如何得到等待的結(jié)果呢,如果bWaitAll設(shè)置為TRUE,將返回值和WAIT_OBJECT_0比較,如果相等則全部句柄都已
發(fā)出了完成信號, 如果bWaitAll設(shè)置為FALSE, 如果只由一個發(fā)出信號,那么將返回值減去WAIT_OBJECT_0就是句
柄數(shù)組中的索引,如果有多個信號發(fā)出,那么這個值是數(shù)組中最小索引的那一個.這樣就可以判斷是哪個發(fā)出了完成信號.
通常,這些要等待的Objects是在其他的線程中執(zhí)行的,那么執(zhí)行完成后調(diào)用SetEvent( HANDLE hObjHandle )就可以
發(fā)出一個完成信號,供調(diào)用WaitForMultipleObjects的線程接收.
以下是一個如何使用該函數(shù)的簡單例子,它使用CreateEvent函數(shù)創(chuàng)建了2個事件對象,放入全局的ghEvents緩存,然后
創(chuàng)建了一個線程,等待該線程發(fā)出完成信號.
//
// Sync01.cpp
//
#include <windows.h>
#include <stdio.h>
HANDLE ghEvents[2];
DWORD WINAPI ThreadProc( LPVOID );
void main()
{
HANDLE hThread;
DWORD i, dwEvent, dwThreadID;
// Create two event objects
for (i = 0; i < 2; i++)
{
ghEvents[i] = CreateEvent(
NULL, // default security attributes
FALSE, // auto-reset event object
FALSE, // initial state is nonsignaled
NULL); // unnamed object
if (ghEvents[i] == NULL)
{
printf("CreateEvent error: %d\n", GetLastError() );
ExitProcess(0);
}
}
// Create a thread
hThread = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
NULL, // no thread function arguments
0, // default creation flags
&dwThreadID); // receive thread identifier
if( hThread == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return;
}
// Wait for the thread to signal one of the event objects
dwEvent = WaitForMultipleObjects(
2, // number of objects in array
ghEvents, // array of objects
FALSE, // wait for any object
5000); // five-second wait
// The return value indicates which event is signaled
switch (dwEvent)
{
// ghEvents[0] was signaled
case WAIT_OBJECT_0 + 0:
// TODO: Perform tasks required by this event
printf("First event was signaled.\n");
break;
// ghEvents[1] was signaled
case WAIT_OBJECT_0 + 1:
// TODO: Perform tasks required by this event
printf("Second event was signaled.\n");
break;
case WAIT_TIMEOUT:
printf("Wait timed out.\n");
break;
// Return value is invalid.
default:
printf("Wait error: %d\n", GetLastError());
ExitProcess(0);
}
// Close event handles
for (i = 0; i < 2; i++)
CloseHandle(ghEvents[i]);
}
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
// Set one event to the signaled state
if ( !SetEvent(ghEvents[0]) )
{
printf("SetEvent failed (%d)\n", GetLastError());
return -1;
}
return 1;
}