Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Класс System.Threading.ThreadPool предоставляет приложению пул рабочих потоков, управляемых системой, что позволяет сосредоточиться на задачах приложений, а не на управлении потоками. Если у вас есть короткие задачи, требующие фоновой обработки, управляемый пул потоков — это простой способ воспользоваться несколькими потоками. Использование пула потоков значительно упрощается в платформе .NET Framework 4 и более поздних версиях, так как можно создавать Task и Task<TResult> объекты, выполняющие асинхронные задачи в потоках пула потоков.
.NET использует потоки пула потоков для многих целей, включая операции библиотеки параллельных задач (Task Parallel Library, TPL), асинхронное завершение ввода-вывода, обратные вызовы таймера, зарегистрированные операции ожидания, асинхронные вызовы методов с помощью делегатов и соединения сокетов.
Характеристики пула потоков
Потоки пула потоков — это фоновые потоки. Каждый поток использует размер стека по умолчанию, выполняется с приоритетом по умолчанию и находится в многопоточной среде. Когда поток в пуле потоков завершит свою задачу, он возвращается в очередь ожидающих потоков. С этого момента его можно повторно использовать. Это позволяет приложениям избежать затрат на создание нового потока для каждой задачи.
Для каждого процесса существует только один пул потоков.
Исключения в пуле потоков
Исключения, не обработанные в потоках пула потоков, завершают процесс. Существует три исключения для этого правила:
- В потоке из пула потоков выбрасывается System.Threading.ThreadAbortException, поскольку был вызван Thread.Abort.
- Выбрасывается System.AppDomainUnloadedException в потоке из пула потоков, поскольку домен приложения выгружается.
- Общая среда выполнения или хост-процесс завершает выполнение потока.
Дополнительные сведения см. в разделе "Исключения" в управляемых потоках.
Максимальное количество потоков пула потоков
Количество операций, которые можно вставить в пул потоков, ограничено только доступной памятью. Однако пул потоков ограничивает количество потоков, которые могут быть активными в процессе одновременно. Если все потоки пула потоков заняты, дополнительные задачи помещаются в очередь до тех пор, пока потоки не будут доступны. Размер пула потоков по умолчанию для процесса зависит от нескольких факторов, таких как размер виртуального адресного пространства. Процесс может вызвать ThreadPool.GetMaxThreads метод, чтобы определить количество потоков.
Максимальное количество потоков можно контролировать с помощью методов ThreadPool.GetMaxThreads и ThreadPool.SetMaxThreads.
Замечание
Код, в котором размещена среда CLR, может задать размер с помощью метода ICorThreadpool::CorSetMaxThreads
.
Минимальные значения пула потоков
Пул потоков предоставляет новые рабочие потоки или потоки завершения ввода-вывода по запросу, пока не достигнет указанного минимального значения для каждой категории. Этот метод можно использовать для получения этих минимальных значений ThreadPool.GetMinThreads .
Замечание
Если спрос низкий, фактическое количество потоков в пуле может быть ниже минимального числа.
По достижении минимального значения пул потоков может создавать дополнительные потоки или ожидать завершения некоторых задач. Пул потоков создает и уничтожает рабочие потоки для оптимизации пропускной способности, которая определяется как количество задач, которые выполняются за единицу времени. Слишком мало потоков может не обеспечить оптимальное использование доступных ресурсов, в то время как слишком много потоков может усилить конкуренцию за ресурсы.
Осторожность
Метод ThreadPool.SetMinThreads можно использовать для увеличения минимального количества пустующих потоков. Однако ненужно увеличение этих значений может привести к проблемам с производительностью. Если слишком много задач начинаются одновременно, все из них могут быть медленными. В большинстве случаев пул потоков будет работать лучше со своим алгоритмом по выделению потоков.
Использование пула потоков
Самый простой способ использовать пул потоков — использовать библиотеку параллельных задач (TPL). По умолчанию типы TPL, такие как Task и Task<TResult>, используют потоки пула для выполнения задач.
Вы также можете использовать пул потоков, вызвав ThreadPool.QueueUserWorkItem из управляемого кода (или вызвав ICorThreadpool::CorQueueUserWorkItem
из неуправляемого кода) и передав System.Threading.WaitCallback делегат, представляющий метод, выполняющий задачу.
Другой способ использования пула потоков — это постановка рабочих элементов в очередь, связанных с операцией ожидания, с помощью метода ThreadPool.RegisterWaitForSingleObject и передачи System.Threading.WaitHandle, который при сигнале или истечении времени ожидания вызывает метод, представленный делегатом System.Threading.WaitOrTimerCallback. Потоки из пула потоков используются для вызова методов обратного вызова.
В примерах проверьте страницы API, на которые ссылается ссылка.
Пропуск проверок безопасности
Пул потоков также предоставляет методы ThreadPool.UnsafeQueueUserWorkItem и ThreadPool.UnsafeRegisterWaitForSingleObject. Используйте эти методы, только если вы уверены, что стек вызывающего объекта не имеет значения для любых проверок безопасности, выполняемых во время выполнения задачи в очереди. ThreadPool.QueueUserWorkItem и ThreadPool.RegisterWaitForSingleObject оба захватывают стек вызывающего кода, который включается в стек пула потоков, когда поток начинает выполнение задачи. Если требуется проверка безопасности, необходимо проверить весь стек. Хотя проверка обеспечивает безопасность, она также вызывает снижение производительности.
Когда не следует использовать потоки пула потоков
Существует несколько сценариев, в которых целесообразно создать и управлять своими потоками вместо использования пула потоков.
- Требуется поток переднего плана.
- Вам нужно, чтобы поток имел определенный приоритет.
- У вас есть задачи, которые вызывают блокировку потока в течение длительного периода времени. Пул потоков имеет максимальное количество потоков, поэтому большое количество заблокированных потоков пула потоков может препятствовать запуску задач.
- Необходимо разместить потоки в однопоточную модель. Все ThreadPool потоки находятся в многопоточной среде.
- Необходимо иметь стабильную идентичность, связанную с потоком, или выделить поток задаче.