Я установил максимальный поток на 10. Затем я добавил задачу 22000, используя ThreadPool.QueueUserWorkItem. Очень вероятно, что не вся задача 22000 была выполнена после запуска программы. Есть ли ограничение на количество задач, которые могут быть поставлены в очередь для доступных потоков?
Максимальное количество элементов в очереди в ThreadPool.QueueUserWorkItem
Ответы (4)
Очередь не имеет практического ограничения, однако сам пул не будет превышать 64 дескриптора ожидания, т. е. общее количество активных потоков.
Если вам нужно дождаться обработки всех задач, вам нужно справиться с этим самостоятельно. Все потоки 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 или около того, вероятно, немного улучшит вашу общую пропускную способность...
Это вопрос, зависящий от реализации, и реализация этой функции со временем немного изменилась. Но в .Net 4.0 вы существенно ограничены объемом памяти в системе, поскольку задачи хранятся в очереди в памяти. Вы можете увидеть это, покопавшись в реализации в рефлекторе.
Примечание. Потоки в пуле управляемых потоков являются фоновыми. То есть их свойства IsBackground верны. Это означает, что поток ThreadPool не будет поддерживать выполнение приложения после завершения всех потоков переднего плана.
Возможно ли, что вы выходите до того, как все задачи будут обработаны?