Поделиться через


Пул потоков

Существует множество приложений, создающих потоки, которые тратят много времени в спящем состоянии, ожидая возникновения события. Другие потоки могут входить в спящее состояние, только чтобы периодически пробуждаться и проверять изменения или обновления состояния. Пул потоков обеспечивает более эффективное использование потоков, предоставляя вашему приложению пул рабочих потоков, управляемых системой. По крайней мере один поток следит за состоянием всех операций ожидания, поставленных в очередь пула потоков. После завершения операции ожидания рабочий поток из пула потоков выполняет соответствующую функцию обратного вызова.

В этом разделе описывается исходный API пула потоков. API пула потоков, представленный в Windows Vista, является более простым, более надежным, имеет более высокую производительность и обеспечивает большую гибкость для разработчиков. Для получения информации о текущем API пула потоков, см. пулы потоков.

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

таймеры очереди и операции зарегистрированного ожидания также используют пул потоков. Их функции обратного вызова помещаются в пул потоков. Вы также можете использовать функцию BindIoCompletionCallback для записи асинхронных операций ввода-вывода. При завершении ввода-вывода обратный вызов выполняется потоком из пула.

Пул потоков создается при первом вызове QueueUserWorkItem или BindIoCompletionCallback, или когда таймер очереди или зарегистрированная операция ожидания добавляет функцию обратного вызова в очередь. По умолчанию число потоков, которые можно создать в пуле потоков, составляет около 500. Каждый поток использует размер стека по умолчанию и работает с приоритетом по умолчанию.

В пуле потоков есть два типа рабочих потоков: ввода-вывода и не-ввода-вывода. Рабочий поток ввода-вывода — это поток, который ожидает в состоянии, готовом к оповещению. Рабочие элементы помещаются в очередь в рабочие потоки ввода-вывода в качестве асинхронных вызовов процедур (APC). Если рабочий поток ввода-вывода должен быть выполнен в потоке, который ожидает оповещений, следует ставить рабочий элемент в очередь рабочего потока ввода-вывода.

рабочий поток, отличный от ввода-вывода, ожидает на портах завершения ввода-вывода. Использование рабочих потоков, отличных от операций ввода-вывода, является более эффективным, чем использование рабочих потоков ввода-вывода. Поэтому по возможности следует использовать рабочие потоки, отличные от ввода-вывода. Потоки рабочих операций ввода-вывода и потоки, не выполняющие операции ввода-вывода, не завершаются, если есть ожидающие асинхронные запросы ввода-вывода. Оба типа потоков могут использоваться рабочими элементами, которые инициируют асинхронные запросы на завершение ввода-вывода. Тем не менее, избегайте размещения асинхронных запросов на выполнение операций ввода-вывода в рабочих потоках, отличных от ввода-вывода, если они могут занять много времени.

Чтобы использовать пул потоков, рабочие элементы и все вызываемые функции должны быть потокобезопасными. Безопасная функция не предполагает, что поток, выполняющий его, является выделенным или постоянным потоком. Как правило, следует избегать использования локального хранилища потока или асинхронного вызова, требующего постоянного потока, например функции RegNotifyChangeKeyValue. Однако такие функции можно вызывать в выделенном потоке (созданном приложением) или поставить в очередь для выполнения на постоянном рабочем потоке (используя QueueUserWorkItem с параметром WT_EXECUTEINPERSISTENTTHREAD).

Оповещаемый ввод-вывод

асинхронные вызовы процедур

Порты завершения ввода-вывода

пулы потоков