Waiting for Multiple Objects
在Windows中, WaitForMultipleObjects函数是一种同步的方法,原形定义如下:
DWORD WinApi WaitForMultipleObjects(
DWORD nCount, const Handle * lpHandles, BOOL bWaitAll, DWORD dwMilliseconds );
调用该函数的线程进入等待状态,直到条件满足时继续执行,条件的满足和参数有关.
第一个参数为要等待的Objects的个数,通常这些Objects是一组句柄(Handles),可以是内核对象句柄或者是非内核对象
句柄,这一组句柄由第2个指向分配给一系列句柄缓冲区的指针指出,第3个参数如果为TRUE,则等待的线程必须等到所有
句柄全部完成执行后才继续执行,如果为FALSE, 那么只要有一个返回即可继续执行,第4个参数设置TIMEOUT的时间,
如果在给定的dwMilliseconds内仍没等到条件满足则返回.
那么如何得到等待的结果呢,如果bWaitAll设置为TRUE,将返回值和WAIT_OBJECT_0比较,如果相等则全部句柄都已
发出了完成信号, 如果bWaitAll设置为FALSE, 如果只由一个发出信号,那么将返回值减去WAIT_OBJECT_0就是句
柄数组中的索引,如果有多个信号发出,那么这个值是数组中最小索引的那一个.这样就可以判断是哪个发出了完成信号.
通常,这些要等待的Objects是在其他的线程中执行的,那么执行完成后调用SetEvent( HANDLE hObjHandle )就可以
发出一个完成信号,供调用WaitForMultipleObjects的线程接收.
以下是一个如何使用该函数的简单例子,它使用CreateEvent函数创建了2个事件对象,放入全局的ghEvents缓存,然后
创建了一个线程,等待该线程发出完成信号.
//
// 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;
}