На этом шаге мы рассмотрим синтаксис этих функций.
Windows поддерживает асинхронные вызовы процедур (Asynchronous Procedure Calls, APC). При создании каждого потока с ним ассоциируется очередь асинхронных вызовов процедур (APC queue). Операционная система (или приложение пользователя при помощи функции QueueUserAPC) может помещать в нее запросы на выполнение функций в контексте этого потока. Такие функции нельзя выполнить немедленно, поскольку поток может быть занят. Поэтому операционная система вызывает их, когда поток обращается к одной из следующих функций ожидания:
function SleepEx( dwMilliseconds: DWORD; // Период ожидания bAlertable: BOOL // Задает, должна ли функция возвращать // управление в случае запроса // на асинхронный вызов процедуры ): DWORD; stdcall; function WaitForSingleObjectEx( hHandle: THandle; // Идентификатор объекта dwMilliseconds: DWORD; // Период ожидания bAlertable: BOOL // Задает, должна ли функция возвращать // управление в случае запроса // на асинхронный вызов процедуры ): DWORD; stdcall; function WaitForMultipleObjectsEx( nCount: DWORD; // Количество объектов lpHandles: PWOHandleArray; // Адрес массива идентификаторов объектов bWaitAll: BOOL; // Необходимость ожидания всех или любого из объектов dwMilliseconds: DWORD; // Период ожидания bAlertable: BOOL // Задает, должна ли функция возвращать // управление в случае запроса // на асинхронный вызов процедуры ): DWORD; stdcall; function SignalObjectAndWait( hObjectToSignal: THandle; // Объект, который будет переведен // в сигнальное состояние hObjectToWaitOn: THandle; // Объект, которого ожидает функция dwMilliseconds: DWORD; // Период ожидания bAlertable: BOOL // Задает, должна ли функция возвращать // управление в случае запроса // на асинхронный вызов процедуры ): DWORD; stdcall; function MsgWaitForMultipleObjectsEx( nCount: DWORD; // Количество объектов синхронизации var pHandles; // Адрес массива объектов fWaitAll: BOOL; // Необходимость ожидания всех или любого из объектов dwMilliseconds, // Период ожидания dwWakeMask: DWORD, // Тип события, прерывающего ожидание dwFlags: DWORD // Дополнительные флаги ): DWORD; stdcall;
Если параметр bAlertable равен True (либо параметр dwFlags в функции MsgWaitForMultipleObjectsEx содержит значение MWMO_ALERTABLE), то при появлении в очереди АРС запроса на асинхронный вызов процедуры операционная система выполняет вызовы всех имеющихся в очереди процедур, после чего функция возвращает значение WAIT_IO_COMPLETION.
Такой механизм позволяет реализовать, например, асинхронный ввод-вывод. Поток может инициировать фоновое выполнение одной или нескольких операций ввода-вывода функциями ReadFileEx или WriteFileEx, передав им адреса функций-обработчиков завершения операции. По завершении вызовы этих функций будут поставлены в очередь асинхронного вызова процедур. В свою очередь, инициировавший операции поток, когда он будет готов обработать результаты, может, используя одну из вышеприведенных функций ожидания, позволить операционной системе вызвать функции-обработчики. Поскольку очередь АРС реализована на уровне ядра операционной системы, она более эффективна, чем очередь сообщений, и позволяет реализовать гораздо более эффективный ввод-вывод.
Со следующего шага мы начнем рассматривать объекты синхронизации.