internal static bool WaitAll(
IWaitableResult[] waitableResults,
int millisecondsTimeout,
bool exitContext,
WaitHandle cancelWaitHandle)
{
if (0 == waitableResults.Length)
{
return true;
}
bool success;
WaitHandle[] waitHandles = new WaitHandle[waitableResults.Length];
GetWaitHandles(waitableResults, waitHandles);
if ((null == cancelWaitHandle) && (waitHandles.Length <= 64))
{
success = STPEventWaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
}
else
{
success = true;
int millisecondsLeft = millisecondsTimeout;
Stopwatch stopwatch = Stopwatch.StartNew();
WaitHandle[] whs;
if (null != cancelWaitHandle)
{
whs = new WaitHandle[] { null, cancelWaitHandle };
}
else
{
whs = new WaitHandle[] { null };
}
bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout);
// Iterate over the wait handles and wait for each one to complete.
// We cannot use WaitHandle.WaitAll directly, because the cancelWaitHandle
// won't affect it.
// Each iteration we update the time left for the timeout.
for (int i = 0; i < waitableResults.Length; ++i)
{
// WaitAny don't work with negative numbers
if (!waitInfinitely && (millisecondsLeft < 0))
{
success = false;
break;
}
whs[0] = waitHandles[i];
int result = STPEventWaitHandle.WaitAny(whs, millisecondsLeft, exitContext);
if ((result > 0) || (STPEventWaitHandle.WaitTimeout == result))
{
success = false;
break;
}
if (!waitInfinitely)
{
// Update the time left to wait
millisecondsLeft = millisecondsTimeout - (int)stopwatch.ElapsedMilliseconds;
}
}
}
// Release the wait handles
ReleaseWaitHandles(waitableResults);
return success;
}