Darko
Darko

Reputation: 527

Know when ThreadPool is empty

I can;t seem to find an easy way to determine when a ThreadPool has finished with all the queued tasks. I found some answers here but none of which can help me.

For sake of simplicity let's say:

for (int i=0;i<10;i++)
{
   threadpool.queueuserworkitem(Go);

}
void Go()
{
   Console.WriteLine("Hello");
}

So how would I go about sending a final "All done" console.writeline after all the 10 background threads have finished?

Thanks

Upvotes: 5

Views: 4597

Answers (3)

Tyson
Tyson

Reputation: 14734

You wouldn't ask the thread pool, but instead you would get each background thread to provide notification of when it completes.

But don't do that plumbing yourself, use the new TPL and the Task class:

var tasks = new Task[10];
for (int i=0;i<10;i++)
{
    tasks[i] = Task.Factory.StartNew( Go );
}

Task.WaitAll(tasks);
Console.WriteLine("All done");

void Go()
{
   Console.WriteLine("Hello");
}

EDIT: I would question why you want exactly 10 threads performing the work. The default task scheduler already optimizes for the number of CPU cores detected. But if you must, there is an implementation of a TaskScheduler that limits the degree of concurrency to a fixed number here: http://msdn.microsoft.com/en-us/library/ee789351.aspx

Upvotes: 4

joe_coolish
joe_coolish

Reputation: 7259

Have you tried using Reactive Extensions?

Rx makes doing just this very simple. For example, you can rewrite your problem like this:

    private void test()
    {
        var list = Enumerable.Range(0, 10)
            .ToObservable()
            .ObserveOn(Scheduler.ThreadPool)
            .SubscribeOn(Scheduler.ThreadPool)
            .Subscribe(i=>Go(),Done);

    }

    void Go()
    {
        Console.WriteLine("Hello");
    }

    void Done()
    {
        Console.WriteLine("Done");
    }

Super simple. Look into Rx, you'll be glad

Upvotes: 1

ogggre
ogggre

Reputation: 2264

It is impossible and dangerous to rely on thread pool emptiness. What you can do is to count your active tasks yourself. A low level approach with monitor:

   class Program
    {
        static object _ActiveWorkersLock = new object();
        static int _CountOfActiveWorkers;

        static void Go(object state)
        {
            try
            {
                Console.WriteLine("Hello");
            }
            finally
            {
                lock (_ActiveWorkersLock)
                {
                    --_CountOfActiveWorkers;
                    Monitor.PulseAll(_ActiveWorkersLock);
                }
            }
        }

        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
            {
                lock (_ActiveWorkersLock)
                    ++_CountOfActiveWorkers;
                ThreadPool.QueueUserWorkItem(Go);
            }

            lock (_ActiveWorkersLock)
            {
                while (_CountOfActiveWorkers > 0)
                    Monitor.Wait(_ActiveWorkersLock);
            }

            Console.WriteLine("All done");
        }
    }

Upvotes: 0

Related Questions