Выполнение асинхронного вызова

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

Для каждого метода в синхронном интерфейсе соответствующий асинхронный интерфейс реализует два метода. Эти методы присоединяют префиксы Begin_ и Finish_ к имени синхронного метода. Например, если интерфейс с именем ISimpleStream имеет метод Read, интерфейс AsyncISimpleStream будет иметь Begin_Read и метод Finish_Read. Чтобы начать асинхронный вызов, клиент вызывает метод Begin_.

Начало асинхронного вызова

  1. Запросите объект сервера для интерфейса ICallFactory. Если QueryInterface возвращает E_NOINTERFACE, объект сервера не поддерживает асинхронный вызов.

  2. Вызовите ICallFactory::CreateCall, чтобы создать объект вызова, соответствующий нужному интерфейсу, а затем освободить указатель на ICallFactory.

  3. Если вы не запросили указатель на асинхронный интерфейс из вызова CreateCall, запросите объект вызова для асинхронного интерфейса.

  4. Вызовите соответствующий метод Begin_.

Теперь серверный объект обрабатывает асинхронный вызов, и клиент может выполнять другие действия, пока он не нуждается в результатах вызова.

Объект вызова может обрабатывать только один асинхронный вызов за раз. Если тот же или второй клиент вызывает метод Begin_ до завершения ожидающего асинхронного вызова, метод Begin_ вернет RPC_E_CALL_PENDING.

Если клиенту не нужны результаты метода Begin_, он может освободить объект вызова в конце этой процедуры. COM обнаруживает это условие и очищает вызов. Метод Finish_ не вызывается, и клиент не получает никаких параметров или возвращаемого значения.

Когда объект сервера готов к возврату из метода Begin_, он сообщает объекту вызова, который он выполняет. Когда клиент готов, он проверка, чтобы узнать, был ли сигнал объекта вызова. В этом случае клиент может завершить асинхронный вызов.

Механизм для этого сигнала и проверка между клиентом и сервером — это интерфейс ISynchronize в объекте вызова. Объект вызова обычно реализует этот интерфейс путем агрегирования объекта синхронизации, предоставленного системой. Объект синхронизации упаковывает дескриптор событий, который сервер сигнализирует непосредственно перед возвращением из метода Begin_ путем вызова ISynchronize::Signal.

Завершение асинхронного вызова

  1. Запрос объекта вызова для интерфейса ISynchronize.

  2. Вызов ISynchronize ::Wait.

  3. Если ожидание возвращает RPC_E_TIMEOUT, метод Begin_ не завершает обработку. Клиент может продолжить работу и снова вызвать ожидание позже. Он не может вызывать метод Finish_, пока ожидание не возвращает S_OK.

    Если ожидание возвращает S_OK, метод Begin_ возвращается. Вызовите соответствующий метод Finish_.

Метод Finish_ передает клиенту любые параметры. Поведение асинхронных методов, включая возвращаемое значение метода Finish_, должно соответствовать точно тому, что соответствующего синхронного метода.

Клиент может освободить объект вызова, как только метод Finish_ возвращается, или он может содержать указатель на объект вызова для выполнения дополнительных вызовов. В любом случае клиент несет ответственность за освобождение объекта вызова, если объект больше не нужен.

При вызове метода Finish_ при отсутствии вызова метод вернет RPC_E_CALL_COMPLETE.

Примечание.

Если клиентские и серверные объекты находятся в одной квартире, вызовы ICallFactory::CreateCall не гарантированы успешно. Если объект сервера не поддерживает асинхронный вызов определенного интерфейса, попытка создания объекта вызова завершится ошибкой, и клиент должен использовать синхронный интерфейс.

 

Отмена асинхронного вызова

Безопасность клиента во время асинхронного вызова

Олицетворение и асинхронные вызовы