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


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

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

Каждый поток имеет собственную очередь APC. Приложение очереди APC в поток путем вызова функции QueueUserAPC. Вызывающий поток задает адрес функции APC в вызове QueueUserAPC. Очередь APC — это запрос на вызов функции APC.

Когда APC в пользовательском режиме помещается в очередь, поток, к которому он помещается в очередь, не направляется для вызова функции APC, если она не находится в состоянии оповещения. Поток вводит оповещенное состояние при вызове SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx, WaitForMultipleObjectsExили функции WaitForSingleObjectEx. Если ожидание удовлетворено до очереди APC, поток больше не находится в состоянии ожидания, чтобы функция APC не выполнялась. Однако APC по-прежнему находится в очереди, поэтому функция APC будет выполняться, когда поток вызывает другую оповещенную функцию ожидания.

ReadFileEx, SetWaitableTimer, SetWaitableTimerExи функции WriteFileEx реализуются с помощью APC в качестве механизма обратного вызова уведомления о завершении.

Если вы используете пул потоков, обратите внимание, что API не работают, а также другие механизмы сигнализации, так как система управляет временем существования потоков пула потоков, поэтому перед доставкой уведомления можно завершить поток. Вместо использования механизма передачи сигналов на основе APC, например параметра pfnCompletionRoutineSetWaitableTimer или SetWaitableTimerEx, используйте объект ожидания, созданный с помощью таймера CreateThreadpoolTimer. Для ввода-вывода используйте объект завершения ввода-вывода, созданный с помощью CreateThreadpoolIo или hEventна основе OVERLAPPED структуры, в которой событие можно передать в функцию setThreadpoolWait.

Внутренние данные синхронизации

При выдаче запроса ввода-вывода структура выделяется для представления запроса. Эта структура называется пакетом запросов ввода-вывода (IRP). При синхронном вводе-вывод поток создает IRP, отправляет его в стек устройств и ожидает завершения IRP в ядре. При использовании асинхронного ввода-вывода поток создает IRP и отправляет его в стек устройств. Стек может немедленно завершить IRP или возвратить ожидающее состояние, указывающее, что запрос выполняется. Когда это происходит, IRP по-прежнему связан с потоком, поэтому он будет отменен, если поток завершает работу или вызывает функцию, например CancelIo. В то же время поток может продолжать выполнять другие задачи, пока стек устройств продолжает обрабатывать IRP.

Система может указать, что IRP завершена несколькими способами:

  • Обновите перекрываемую структуру с результатом операции, чтобы поток смог провести опрос, чтобы определить, выполнена ли операция.
  • Сообщите о событии в перекрывающейся структуре, чтобы поток синхронизироваться с событием и проснуться после завершения операции.
  • В очереди IRP в ожидающий APC потока, чтобы поток выполнял подпрограмму APC, когда он входит в оповещенное состояние ожидания и возвращается из операции ожидания с состоянием, указывающим, что он выполнил одну или несколько подпрограмм APC.
  • Очередь IRP в порт завершения ввода-вывода, где он будет выполняться следующим потоком, который ожидает порта завершения.

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

Использование ожидающего таймера с вызовом асинхронной процедуры