Fazendo a chamada assíncrona
Antes de fazer uma chamada remota assíncrona, o cliente deve inicializar o identificador assíncrono. Os programas cliente e servidor usam ponteiros para a estrutura RPC_ASYNC_STATE para identificadores assíncronos.
Cada chamada pendente deve ter seu próprio identificador assíncrono exclusivo. O cliente cria o identificador e o passa para a função RpcAsyncInitializeHandle . Para que a chamada seja concluída corretamente, o cliente deve garantir que a memória do identificador não seja liberada até receber a resposta assíncrona do servidor. Além disso, antes de fazer outra chamada em um identificador assíncrono existente, o cliente deve reinicializar o identificador. A falha ao fazer isso pode fazer com que o stub do cliente gere uma exceção durante a chamada. O cliente também deve garantir que os buffers fornecidos para parâmetros [out] e parâmetros [in, out] para um procedimento remoto assíncrono permaneçam alocados até que ele tenha recebido a resposta do servidor.
Quando ele invoca um procedimento remoto assíncrono, o cliente deve selecionar o método que a biblioteca de tempo de execução RPC usará para notificá-la sobre a conclusão da chamada. O cliente pode receber essa notificação de qualquer uma das seguintes maneiras:
Evento. O cliente pode especificar um evento a ser acionado quando a chamada for concluída. Para obter detalhes, consulte Objetos de Evento.
Executar a sondagem. O cliente pode chamar RpcAsyncGetCallStatus repetidamente. Se o valor retornado for diferente de RPC_S_ASYNC_CALL_PENDING, a chamada será concluída. Esse método usa mais tempo de CPU do que os outros métodos descritos aqui.
APC. O cliente pode especificar uma APC (chamada de procedimento assíncrona) que é chamada quando a chamada é concluída. Para obter o protótipo da função APC, consulte RPCNOTIFICATION_ROUTINE. A APC é chamada com seu parâmetro Event definido como RpcCallComplete. Para que as APCs sejam enviadas, o thread do cliente deve estar em um estado de espera alertável.
Se o campo hThread no identificador assíncrono estiver definido como 0, as APCs serão enfileiradas no thread que fez a chamada assíncrona. Se não for zero, as APCs serão enfileiradas no thread especificado por m.
IOC. A porta de conclusão de E/S é notificada com os parâmetros especificados no identificador assíncrono. Para obter mais informações, consulte CreateIoCompletionPort.
Identificador do Windows. Uma mensagem é postada no identificador de janela especificado (HWND).
O fragmento de código a seguir mostra as etapas essenciais necessárias para inicializar um identificador assíncrono e usá-lo para fazer uma chamada de procedimento remoto assíncrono.
RPC_ASYNC_STATE Async;
RPC_STATUS status;
// Initialize the handle.
status = RpcAsyncInitializeHandle(&Async, sizeof(RPC_ASYNC_STATE));
if (status)
{
// Code to handle the error goes here.
}
Async.UserInfo = NULL;
Async.NotificationType = RpcNotificationTypeEvent;
Async.u.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (Async.u.hEvent == 0)
{
// Code to handle the error goes here.
}
// Call an asynchronous RPC routine here
RpcTryExcept
{
printf("\nCalling the remote procedure 'AsyncFunc'\n");
AsyncFunc(&Async, AsyncRPC_ClientIfHandle, nAsychDelay);
}
RpcExcept(1)
{
ulCode = RpcExceptionCode();
printf("AsyncFunc: Run time reported exception 0x%lx = %ld\n",
ulCode, ulCode);
}
RpcEndExcept
// Call a synchronous routine while
// the asynchronous procedure is still running
RpcTryExcept
{
printf("\nCalling the remote procedure 'NonAsyncFunc'\n");
NonAsyncFunc(AsyncRPC_ClientIfHandle, pszMessage);
fprintf(stderr,
"While 'AsyncFunc' is running asynchronously,\n"
"we still can send message to the server in the mean "
"time.\n\n");
}
RpcExcept(1)
{
ulCode = RpcExceptionCode();
printf("NonAsyncFunc: Run time reported exception 0x%lx = %ld\n",
ulCode, ulCode);
}
RpcEndExcept
Como este exemplo demonstra, seu programa cliente pode executar chamadas de procedimento remoto síncronas enquanto uma chamada de procedimento assíncrono ainda está pendente. Esse cliente cria um objeto de evento para a biblioteca de tempo de execução RPC a ser usada para notificá-lo quando a chamada assíncrona for concluída.
Observação
A notificação de conclusão não será retornada de uma rotina de RPC assíncrona se uma exceção RPC for gerada durante uma chamada assíncrona.