Calling WaitAll with array of 64 or more causes exception
WaitHandle.WaitAll(whaWaitHandlesArray);
System.NotSupportedException: The number of WaitHandles must be less
than or equal to 64.
at System.Threading.WaitHandle.WaitAll(WaitHandle[] waitHandles,
Int32 millisecondsTimeout, Boolean exitContext)
at System.Threading.WaitHandle.WaitAll(WaitHandle[] waitHandles)
Searching for the error string revealed no KB article or MSDN
documentation.
I did found MSFT answer regarding that on:
http://groups.google.com/group/microsoft.public.sqlserver.notificationsvcs/tree/
browse_frm/thread/1e10fc93cf194775/1d8e7ee0e1a3f41c
The API documentation says it might throw NotSupportedException under
the condition: "The number of objects in waitHandles is greater than
the system permits."
My questions are:
1. How can I find the system limitation? what does it depends on?
2. Any kb article that will provide link from the exception message to
the real cause will be helpful for all the developers and will save us
google time
(About Google Vs www.Live.com - Live did not find even a single match
...)
Loy
Peter Ritchie [C# MVP] - 25 Dec 2006 01:10 GMT
In .NET 2.0 it's simply hard coded to 64. This is based upon the limit of
object handles that the Win32 function WaitForMultipleObjectsEx can
support--which is documented as being MAXIMUM_WAIT_OBJECTS, or 64.
If you want to wait for more than 64 handles you'll have to break it into
chunks of 64 and create a thread for each <=64 chunk that sets another
WaitHandle that is waited upon in some "main" thread (can't be the main
thread in a WinForms application)--which would give you the ability to wait
on 64 blocks of 64 wait handles. More than that and you'd have to break out
to 3 levels. I think there's an example or two on the web of handling more
than 64 handles...

Signature
Browse http://connect.microsoft.com/VisualStudio/feedback/ and vote.
http://www.peterRitchie.com/blog/
Microsoft MVP, Visual Developer - Visual C#
> Calling WaitAll with array of 64 or more causes exception
> WaitHandle.WaitAll(whaWaitHandlesArray);
[quoted text clipped - 24 lines]
>
> Loy
William Stacey [C# MVP] - 25 Dec 2006 03:06 GMT
Fortunately, WaitAll is easy to implement with any number of handles. Here
is a simple example.
public static void WaitAll(WaitHandle[] handles)
{
if (handles == null)
throw new ArgumentNullException("handles");
foreach (WaitHandle wh in handles)
{
wh.WaitOne();
}
}

Signature
William Stacey [C# MVP]
| Calling WaitAll with array of 64 or more causes exception
| WaitHandle.WaitAll(whaWaitHandlesArray);
[quoted text clipped - 8 lines]
| documentation.
| I did found MSFT answer regarding that on:
http://groups.google.com/group/microsoft.public.sqlserver.notificationsvcs/tree/
browse_frm/thread/1e10fc93cf194775/1d8e7ee0e1a3f41c
| The API documentation says it might throw NotSupportedException under
| the condition: "The number of objects in waitHandles is greater than
[quoted text clipped - 10 lines]
|
| Loy
Ben Voigt - 26 Dec 2006 20:30 GMT
> Fortunately, WaitAll is easy to implement with any number of handles.
> Here
> is a simple example.
Which does not replicate the proper semantics and therefore is vulnerable to
deadlock.
> public static void WaitAll(WaitHandle[] handles)
> {
[quoted text clipped - 35 lines]
> |
> | Loy
William Stacey [C# MVP] - 27 Dec 2006 00:37 GMT
How so?

Signature
William Stacey [C# MVP]
| > Fortunately, WaitAll is easy to implement with any number of handles.
| > Here
| > is a simple example.
|
| Which does not replicate the proper semantics and therefore is vulnerable to
| deadlock.
Peter Ritchie [C# MVP] - 27 Dec 2006 02:30 GMT
My calling WaitOne in a loop like that you're allowing the thread to gain
ownership of a WaitHandle without having ownership of all WaitHandles.
WaitAll does not give ownership of all WaitHandes until all WaitHandles have
entered a signaled state.
WaitAll can be given a timeout, if that timeout expires before all
WaitHandles are signaled the thread never gains ownership of any of the
WaitHandles even if some of them have signaled.
BTW, you'd have this same problem if had to split up more thane 64
WaitHandles across multiple threads with multiple calls to WaitAll...

Signature
Browse http://connect.microsoft.com/VisualStudio/feedback/ and vote.
http://www.peterRitchie.com/blog/
Microsoft MVP, Visual Developer - Visual C#
> How so?
>
[quoted text clipped - 5 lines]
> to
> | deadlock.
William Stacey [C# MVP] - 27 Dec 2006 05:26 GMT
This can get slightly more involved and depends on the handle type. If the
wait events are ManualResetEvents, then a timeout may not matter to your
code as they stay signaled anyway. AutoResetEvents are more an issue as
some may be reset by the WaitOne() call before the timeout and that could
get messy - but can still be workable depending on needs. Semaphores,
however, do change their state even with the win32 waitformultipleobjects as
it waits for each one in turn (so the net effect would be the same as using
the shown implementation). If one understands the potential issues and
takes care, the pattern can prove useful when waiting on many handles.

Signature
William Stacey [C# MVP]
| My calling WaitOne in a loop like that you're allowing the thread to gain
| ownership of a WaitHandle without having ownership of all WaitHandles.
[quoted text clipped - 17 lines]
| > to
| > | deadlock.
Loy - 27 Dec 2006 12:33 GMT
Thank you all for your reply
I implemented the simple workaround with the limitation that it works
only if the handles are not reset again during the wait time.
In my case this is a valid limitation as I wait for objects to close
and the handle is nullified in the objects once it is set.
Being aware of this issue - if there is a correct implementation - why
doesn't the dot net team implement it as part of the framework?
On the documentation side - Need to be clear on how to know your system
limitation
A kb article is the least that I would expect with regard to this
issue.
Am I wrong?
Thanks
Loy
> This can get slightly more involved and depends on the handle type. If the
> wait events are ManualResetEvents, then a timeout may not matter to your
[quoted text clipped - 41 lines]
> | > to
> | > | deadlock.
Ben Voigt - 27 Dec 2006 23:04 GMT
> How so?
I think Peter has done a fantastic job of explaining why this is so. If you
still aren't convinced there is a significant difference between:
WaitForMultipleObjects({A, B, C, D});
and
WaitForSingleObject(A);WaitForSingle(B);WaitForSingle(C);WaitForSingle(D);
then I will be happy to clarify.
> | > Fortunately, WaitAll is easy to implement with any number of handles.
> | > Here
[quoted text clipped - 4 lines]
> to
> | deadlock.
William Stacey [C# MVP] - 28 Dec 2006 21:43 GMT
| I think Peter has done a fantastic job of explaining why this is so.
Totally agree.
| still aren't convinced there is a significant difference between:
|
[quoted text clipped - 3 lines]
|
| then I will be happy to clarify.
Thanks Ben. Not sure there is any confusion on that. I think we/I
meandered into some different areas. All is good. Happy New Year.

Signature
William Stacey [C# MVP]
Ben Voigt - 26 Dec 2006 20:31 GMT
> Calling WaitAll with array of 64 or more causes exception
> WaitHandle.WaitAll(whaWaitHandlesArray);
[quoted text clipped - 4 lines]
> Int32 millisecondsTimeout, Boolean exitContext)
> at System.Threading.WaitHandle.WaitAll(WaitHandle[] waitHandles)
At this point you should re-architect your application to use fewer wait
handles. What kind of object are you waiting on and why do you need so
many?
> Searching for the error string revealed no KB article or MSDN
> documentation.
[quoted text clipped - 15 lines]
>
> Loy