转: http://www.ksingla.net/2010/01/waitforallobjects-to-wait-on-more-than-maximum_wait_objects-handles/
typedef struct _WAIT_THREAD_INFORMATION
{
DWORD dwWaitObjectCount;
PHANDLE pWaitHandles;
DWORD dwWaitMSeconds;
} WAIT_THREAD_INFORMATION, *PWAIT_THREAD_INFORMATION;
VOID
WaitForAllObjects(
DWORD dwWaitHandleCount,
HANDLE * pWaitHandles,
DWORD dwMaxWaitMSeconds
)
{
HANDLE * pThreadWaitHandles = NULL;
WAIT_THREAD_INFORMATION * pWaitInformationArray = NULL;
DWORD dwThreadCount = 0;
DWORD dwLastWaitCount = 0;
DWORD dwWaitHandleIndex = 0;
DWORD dwMaximumWaitObjects = MAXIMUM_WAIT_OBJECTS;
ASSERT( dwWaitHandleCount > 0 );
ASSERT( pWaitHandles != NULL );
ASSERT( dwMaxWaitMSeconds >= 1000 );
ASSERT( dwMaximumWaitObjects <= MAXIMUM_WAIT_OBJECTS );
if( dwWaitHandleCount <= dwMaximumWaitObjects )
{
WaitForMultipleObjects( dwWaitHandleCount,
pWaitHandles,
TRUE,
dwMaxWaitMSeconds );
}
else
{
//
// Create separate threads to wait on maximum wait objects
// and then make this thread wait on thread handles
//
dwThreadCount = dwWaitHandleCount / dwMaximumWaitObjects;
dwLastWaitCount = dwWaitHandleCount % dwMaximumWaitObjects;
if( dwLastWaitCount > 0 )
{
dwThreadCount++;
}
//
// This function can handle a maximum of
// MAXIMUM_WAIT_OBJECTS * MAXIMUM_WAIT_OBJECT handles
//
if( dwThreadCount > dwMaximumWaitObjects )
{
dwThreadCount = dwMaximumWaitObjects;
dwLastWaitCount = 0;
}
pThreadWaitHandles = new HANDLE[ dwThreadCount ];
pWaitInformationArray = new WAIT_THREAD_INFORMATION[ dwThreadCount ];
if( pThreadWaitHandles == NULL || pWaitInformationArray == NULL )
{
//
// Failure
//
goto Finished;
}
for( DWORD count = 0; count < dwThreadCount; count++)
{
//
// Set information for the thread
//
pWaitInformationArray[ count ].dwWaitMSeconds =
dwMaxWaitMSeconds;
pWaitInformationArray[ count ].pWaitHandles =
&pWaitHandles[ dwWaitHandleIndex ];
if( count != dwThreadCount - 1 || dwLastWaitCount == 0 )
{
pWaitInformationArray[ count ].dwWaitObjectCount =
dwMaximumWaitObjects;
dwWaitHandleIndex += dwMaximumWaitObjects;
}
else
{
pWaitInformationArray[count].dwWaitObjectCount =
dwLastWaitCount;
dwWaitHandleIndex += dwLastWaitCount;
}
pThreadWaitHandles[ count ] =
CreateThread( NULL,
0,
WaitForMultipleObjectsThread,
&pWaitInformationArray[ count ],
0,
NULL );
if( pThreadWaitHandles[ count ] == NULL )
{
//
// Not able to create threads break from the loop
// and wait for threads we already created.
// dwThreadCount doesnt include this iteration
//
dwThreadCount = count;
break;
}
}
//
// Failure is ignored
//
WaitForMultipleObjects( dwThreadCount,
pThreadWaitHandles,
TRUE,
dwMaxWaitMSeconds );
}
Finished:
if( pThreadWaitHandles != NULL )
{
for( DWORD count = 0; count < dwThreadCount; count++)
{
if( pThreadWaitHandles[ count ] != NULL )
{
CloseHandle( pThreadWaitHandles[ count ] );
pThreadWaitHandles[ count ] = NULL;
}
}
delete [] pThreadWaitHandles;
pThreadWaitHandles = NULL;
}
if( pWaitInformationArray != NULL )
{
delete [] pWaitInformationArray;
pWaitInformationArray = NULL;
}
return;
}
//static
DWORD
WINAPI
WaitForMultipleObjectsThread(
LPVOID lpParameter = NULL
)
//
// Thread routine which calls WaitForMultipleObjects
// This is used to wait for more than MAXIMUM_WAIT_OBJECTS objects
//
{
DWORD dwReturnValue = 0;
PWAIT_THREAD_INFORMATION pThreadInformation = NULL;
ASSERT( lpParameter != NULL );
pThreadInformation = ( PWAIT_THREAD_INFORMATION )lpParameter;
ASSERT(pThreadInformation->dwWaitObjectCount <= MAXIMUM_WAIT_OBJECTS );
ASSERT(pThreadInformation->pWaitHandles != NULL );
ASSERT(pThreadInformation->dwWaitMSeconds != INFINITE );
ASSERT(pThreadInformation->dwWaitMSeconds >= 1000 );
dwReturnValue = WaitForMultipleObjects(
pThreadInformation->dwWaitObjectCount,
pThreadInformation->pWaitHandles,
TRUE,
pThreadInformation->dwWaitMSeconds );
return dwReturnValue;
}
Sample usage of this method will look like below.
//
// Allocate memory for wait handle array
//
pWaitHandles = new HANDLE[ dwWaitHandleCount ];
...
//
// Call WaitForAllObjects
//
WaitForAllObjects( dwWaitHandleCount,
pWaitHandles,
dwMaximumWait );
...
//
// Free memory held by pWaitHandles
//
if( pWaitHandles != NULL )
{
delete [] pWaitHandles;
pWaitHandles = NULL;
}