Partilhar via


Realizar 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 controlos assíncronos.

Cada chamada pendente deve ter seu próprio identificador assíncrono exclusivo. O cliente cria o identificador e passa-o 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 em 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 os parâmetros [out] e [in, out] de um procedimento remoto assíncrono permaneçam alocados até que receba a resposta do servidor.

Quando 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á-lo da conclusão da chamada. O cliente pode receber esta notificação de qualquer uma das seguintes formas:

  • Evento. O cliente pode especificar um evento a ser disparado quando a chamada estiver concluída. Para obter detalhes, consulte Event Objects.

  • Votação. O cliente pode chamar repetidamente RpcAsyncGetCallStatus. Se o valor de retorno for diferente de RPC_S_ASYNC_CALL_PENDING, a chamada será concluída. Este método usa mais tempo de CPU do que os outros métodos descritos aqui.

  • APC. O cliente pode especificar um de chamada de procedimento assíncrono (APC) que é chamado quando a chamada é concluída. Para o protótipo da função APC, consulte RPCNOTIFICATION_ROUTINE. O APC é chamado com seu parâmetro Event definido como RpcCallComplete. Para que os APCs sejam despachados, 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, os APCs serão enfileirados no thread que fez a chamada assíncrona. Se for diferente de zero, os APCs serão enfileirados no thread especificado por m.

  • COI. A porta de conclusão de E/S é notificada com os parâmetros especificados no manipulador assíncrono. Para obter mais informações, consulte CreateIoCompletionPort.

  • Manipulador 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íncrona ainda está pendente. Esse cliente cria um objeto de evento para a biblioteca de tempo de execução RPC usar para notificá-la quando a chamada assíncrona for concluída.

Observação

A notificação de conclusão não será retornada de uma rotina RPC assíncrona se uma exceção RPC for gerada durante uma chamada assíncrona.