Группировка потоков в пул
Существует множество приложений, создающих потоки, которые проводят много времени в спящем состоянии в ожидании события. Другие потоки могут переходить в спящее состояние только для периодического пробуждения для опроса сведений об изменении или обновлении сведений о состоянии. Пул потоков позволяет более эффективно использовать потоки, предоставляя приложению пул рабочих потоков, управляемых системой. По крайней мере один поток отслеживает состояние всех операций ожидания, помещенных в пул потоков. После завершения операции ожидания рабочий поток из пула потоков выполняет соответствующую функцию обратного вызова.
В этом разделе описывается исходный API пула потоков. API пула потоков, представленный в Windows Vista, проще, надежнее, имеет лучшую производительность и обеспечивает большую гибкость для разработчиков. Сведения об API текущего пула потоков см. в разделе Пулы потоков.
Вы также можете помещать в очередь рабочие элементы, не связанные с операцией ожидания, в пул потоков. Чтобы запросить обработку рабочего элемента потоком в пуле потоков, вызовите функцию QueueUserWorkItem . Эта функция принимает параметр функции, которая будет вызываться потоком, выбранным из пула потоков. Отменить рабочий элемент после его постановки в очередь невозможно.
Таймеры очереди таймеров и зарегистрированные операции ожидания также используют пул потоков. Их функции обратного вызова помещаются в очередь в пул потоков. Вы также можете использовать функцию BindIoCompletionCallback для выполнения асинхронных операций ввода-вывода. После завершения операций ввода-вывода обратный вызов выполняется потоком пула потоков.
Пул потоков создается при первом вызове QueueUserWorkItem или BindIoCompletionCallback или при том, что таймер очереди таймера или зарегистрированная операция ожидания помещает в очередь функцию обратного вызова. По умолчанию количество потоков, которые можно создать в пуле потоков, составляет около 500. Каждый поток использует размер стека по умолчанию и выполняется с приоритетом по умолчанию.
Существует два типа рабочих потоков в пуле потоков: ввод-вывод и другие. Рабочий поток ввода-вывода — это поток, который ожидает в состоянии ожидания с возможностью предупреждения. Рабочие элементы помещаются в очередь в рабочие потоки ввода-вывода в виде асинхронных вызовов процедур (APC). Рабочий элемент следует ставить в очередь в рабочий поток ввода-вывода, если он должен выполняться в потоке, который ожидается в состоянии предупреждения.
Рабочий поток, отличный от ввода-вывода, ожидает портов завершения ввода-вывода. Использование рабочих потоков, не относящихся к вводу-выводу, более эффективно, чем рабочих потоков ввода-вывода. Поэтому по возможности следует использовать рабочие потоки, не относящиеся к вводу-выводу. Потоки ввода-вывода и рабочие потоки, не связанные с вводом-выводом, не завершаются, если есть ожидающие асинхронные запросы ввода-вывода. Оба типа потоков могут использоваться рабочими элементами, которые инициируют асинхронные запросы на завершение ввода-вывода. Однако избегайте публикации асинхронных запросов завершения ввода-вывода в рабочих потоках, не относящихся к вводу-выводу, если выполнение может занять много времени.
Чтобы использовать пул потоков, рабочие элементы и все вызываемые ими функции должны быть безопасными для пула потоков. Безопасная функция не предполагает, что выполняющий ее поток является выделенным или постоянным потоком. Как правило, следует избегать использования локального хранилища потока или асинхронного вызова, требующего постоянного потока, например функции RegNotifyChangeKeyValue . Однако такие функции можно вызывать в выделенном потоке (созданном приложением) или помещать в очередь в постоянный рабочий поток (с помощью QueueUserWorkItem с параметром WT_EXECUTEINPERSISTENTTHREAD).
Связанные темы