Search code examples
c#multithreadingwaithandle

Workaround for the WaitHandle.WaitAll 64 handle limit?


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();

Solution

  • 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();