2010-01-19 3 views
7

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

ответ

6

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

+0

Ошибка вызвала мою проблему, но в основном ответ на этот вопрос. –

+0

Спасибо @keith. Таким образом, похоже, что единственным реальным ограничением размера очереди является размер общего объекта Queue (или аналогичного). – matrixugly

+0

Что? У меня 150 потоков потока потоков активны! – Vlad

4

От documentation of ThreadPool:

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

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

4

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

11

Если вам нужно подождать, пока все задачи будут обработаны, вам нужно будет справиться с этим самостоятельно. Нити 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 или около того, вероятно, поможет вашей общей пропускной способности совсем немного ...

+0

Хорошая идея, но приложение ожидало всех потоков. Группировка - тоже очень хорошее предложение. –

Смежные вопросы