Максимальное количество элементов в очереди в ThreadPool.QueueUserWorkItem

Я установил максимальный поток на 10. Затем я добавил задачу 22000, используя ThreadPool.QueueUserWorkItem. Очень вероятно, что не вся задача 22000 была выполнена после запуска программы. Есть ли ограничение на количество задач, которые могут быть поставлены в очередь для доступных потоков?


person Andras Csehi    schedule 19.01.2010    source источник


Ответы (4)


Очередь не имеет практического ограничения, однако сам пул не будет превышать 64 дескриптора ожидания, т. е. общее количество активных потоков.

person keithwarren7    schedule 19.01.2010
comment
Ошибка вызвала мою проблему, но в основном ответ на вопрос таков. - person Andras Csehi; 21.01.2010
comment
Спасибо @кейт. Таким образом, похоже, что единственным реальным ограничением размера очереди является размер самого общего объекта Queue (или аналогичного). - person C. Tewalt; 15.01.2016

Если вам нужно дождаться обработки всех задач, вам нужно справиться с этим самостоятельно. Все потоки ThreadPool являются фоновыми потоками и не будут поддерживать работоспособность приложения.

Это относительно чистый способ справиться с ситуацией такого типа:

 using (var mre = new ManualResetEvent(false))
 {
      int remainingToProcess = workItems.Count(); // Assuming workItems is a collection of "tasks"
      foreach(var item in workItems)
      {
           // Delegate closure (in C# 4 and earlier) below will 
           // capture a reference to 'item', resulting in
           // the incorrect item sent to ProcessTask each iteration.  Use a local copy
           // of the 'item' variable instead.
           // C# 5/VS2012 will not require the local here.
           var localItem = item;
           ThreadPool.QueueUserWorkItem(delegate
           {
               // Replace this with your "work"
               ProcessTask(localItem);

               // This will (safely) decrement the remaining count, and allow the main thread to continue when we're done
               if (Interlocked.Decrement(ref remainingToProcess) == 0)
                      mre.Set();
           });
      }
      mre.WaitOne();
 }

При этом обычно лучше «группировать» вместе ваши рабочие элементы, если у вас их тысячи, а не рассматривать их как отдельные рабочие элементы для пула потоков. Это некоторые накладные расходы, связанные с управлением списком элементов, и, поскольку вы не сможете обрабатывать 22000 элементов за раз, вам лучше сгруппировать их в блоки. Наличие отдельных рабочих элементов в каждом процессе 50 или около того, вероятно, немного улучшит вашу общую пропускную способность...

person Reed Copsey    schedule 19.01.2010
comment
Хорошая идея, но приложение ждало всех потоков. Группировка также является очень хорошим предложением. - person Andras Csehi; 21.01.2010

Это вопрос, зависящий от реализации, и реализация этой функции со временем немного изменилась. Но в .Net 4.0 вы существенно ограничены объемом памяти в системе, поскольку задачи хранятся в очереди в памяти. Вы можете увидеть это, покопавшись в реализации в рефлекторе.

person JaredPar    schedule 19.01.2010

Из документации ThreadPool:

Примечание. Потоки в пуле управляемых потоков являются фоновыми. То есть их свойства IsBackground верны. Это означает, что поток ThreadPool не будет поддерживать выполнение приложения после завершения всех потоков переднего плана.

Возможно ли, что вы выходите до того, как все задачи будут обработаны?

person Joey    schedule 19.01.2010