Знать, когда ThreadPool пуст - PullRequest
       27

Знать, когда ThreadPool пуст

4 голосов
/ 25 февраля 2012

Я не могу найти простой способ определить, когда ThreadPool завершил все поставленные в очередь задачи.Я нашел здесь несколько ответов, но ни один из них не может помочь мне.

Ради простоты, скажем:

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

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

Итак, как бы я отправил окончательную консоль "Все готово".Writeline после того, как все 10 фоновых потоков закончили?

Спасибо

Ответы [ 3 ]

3 голосов
/ 25 февраля 2012

Вы не будете спрашивать пул потоков, но вместо этого вы будете получать каждый фоновый поток для уведомления о том, когда он завершится.

Но не делайте этого самостоятельно, используйте новый TPL и Task класс:

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");
}

РЕДАКТИРОВАТЬ: Я хотел бы спросить, почему вы хотите ровно 10 потоков, выполняющих работу.Планировщик задач по умолчанию уже оптимизирует количество обнаруженных ядер ЦП.Но если вам необходимо, есть реализация TaskScheduler, которая ограничивает степень параллелизма фиксированным числом: http://msdn.microsoft.com/en-us/library/ee789351.aspx

1 голос
/ 25 февраля 2012

Вы пытались использовать Reactive Extensions ?

Rx делает это очень просто.Например, вы можете переписать вашу проблему следующим образом:

    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");
    }

Супер просто.Загляните в Rx, вы будете рады

0 голосов
/ 25 февраля 2012

Невозможно и опасно полагаться на пустоту пула потоков. Что вы можете сделать, так это подсчитать свои активные задачи самостоятельно. Низкоуровневый подход с монитором:

   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");
        }
    }
...