DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 15.10 Waiting for All Threads in theThread Pool to Finish

Problem

For threads that are manually created via the Thread class, you can call the Join method to wait for a thread to finish. This works well when you need to wait for all threads to finish processing before an application terminates. Unfortunately, the thread pool threads do not have a Join method. You need to make sure that all threads in the thread pool have finished processing before another thread terminates or your application's main thread terminates.

Solution

Use a combination of the ThreadPool methods—GetMaxThreads and GetAvailableThreads—to determine when the ThreadPool is finished processing the requests:

public static void Main( )
{
    for(int i=0;i<25;i++)
    {
        // have to wait or threadpool never gives out threads to requests
        Thread.Sleep(50);
        // queue thread request
        ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc),i);
    }
    // have to wait here or the background threads in the thread
    // pool would not run before the main thread exits.
    Console.WriteLine("Main Thread waiting to complete...");
    bool working = true;
    int workerThreads = 0;
    int completionPortThreads = 0;
    int maxWorkerThreads = 0;
    int maxCompletionPortThreads = 0;
    // get max threads in the pool
    ThreadPool.GetMaxThreads(out maxWorkerThreads,out maxCompletionPortThreads);
    while(working)
    {
        // get available threads
        ThreadPool.GetAvailableThreads(out workerThreads,out completionPortThreads);
        if(workerThreads == maxWorkerThreads)
        {
            // allow to quit
            working = false;
        }
        else
        {
            // sleep before checking again
            Thread.Sleep(500);
        }
    }
    Console.WriteLine("Main Thread completing...");
}
Static void ThreadProc(Object stateInfo)
{
    //show we did something with this thread...
    Console.WriteLine("Thread {0} running...", stateInfo);
    Thread.Sleep(1000);
}

Discussion

This approach is a bit coarse; since the CLR does not allow access to the thread objects being created, the best we can do is to see when the ThreadPool no longer has requests queued. If this approach is not sufficient for your needs, you could implement your own thread pool, but be careful of the many pitfalls that await you because thread pools are not easy to get right in all cases. Some of the issues are having too many or too few threads to service requests, determining initial levels of threads in the pool, and deadlocking threads.

See Also

See the "ThreadPool Class" topic in the MSDN documentation. Also see Applied Microsoft .NET Framework Programming by Jeffrey Richter (Wintellect).

    [ Team LiB ] Previous Section Next Section