My application spawns loads of different small worker threads via ThreadPool.QueueUserWorkItem
which I keep track of via multiple ManualResetEvent
instances. I use the WaitHandle.WaitAll
method to block my application from closing until these threads have completed.
I have never had any issues before, however, as my application is coming under more load i.e. more threads being created, I am now beginning to get this exception:
WaitHandles must be less than or equal to 64 - missing documentation
What is the best alternative solution to this?
Code Snippet
List<AutoResetEvent> events = new List<AutoResetEvent>();
// multiple instances of...
var evt = new AutoResetEvent(false);
events.Add(evt);
ThreadPool.QueueUserWorkItem(delegate
{
// do work
evt.Set();
});
...
WaitHandle.WaitAll(events.ToArray());
Workaround
int threadCount = 0;
ManualResetEvent finished = new ManualResetEvent(false);
...
Interlocked.Increment(ref threadCount);
ThreadPool.QueueUserWorkItem(delegate
{
try
{
// do work
}
finally
{
if (Interlocked.Decrement(ref threadCount) == 0)
{
finished.Set();
}
}
});
...
finished.WaitOne();
Create a variable that keeps track of the number of running tasks:
int numberOfTasks = 100;
Create a signal:
ManualResetEvent signal = new ManualResetEvent(false);
Decrement the number of tasks whenever a task is finished:
if (Interlocked.Decrement(ref numberOftasks) == 0)
{
If there is no task remaining, set the signal:
signal.Set();
}
Meanwhile, somewhere else, wait for the signal to be set:
signal.WaitOne();