Compartir a través de


Realización de la llamada asincrónica

Para poder realizar una llamada remota asincrónica, el cliente debe inicializar el identificador asincrónico. Los programas cliente y servidor usan punteros a la estructura de RPC_ASYNC_STATE para identificadores asincrónicos.

Cada llamada pendiente debe tener su propio identificador asincrónico único. El cliente crea el identificador y lo pasa a la función RpcAsyncInitializeHandle . Para que la llamada se complete correctamente, el cliente debe asegurarse de que la memoria del identificador no se libere hasta que reciba la respuesta asincrónica del servidor. Además, antes de realizar otra llamada en un identificador asincrónico existente, el cliente debe reinicializar el identificador. Si no se hace esto, el código auxiliar del cliente puede generar una excepción durante la llamada. El cliente también debe asegurarse de que los búferes que proporciona para los parámetros [out] y los parámetros [in, out] a un procedimiento remoto asincrónico permanecen asignados hasta que haya recibido la respuesta del servidor.

Cuando invoca un procedimiento remoto asincrónico, el cliente debe seleccionar el método que usará la biblioteca en tiempo de ejecución rpc para notificarle la finalización de la llamada. El cliente puede recibir esta notificación de cualquiera de las siguientes maneras:

  • Evento: El cliente puede especificar un evento que se desencadenará cuando se haya completado la llamada. Para obtener más información, consulte Objetos de eventos.

  • Sondeo. El cliente puede llamar repetidamente a RpcAsyncGetCallStatus. Si el valor devuelto es distinto de RPC_S_ASYNC_CALL_PENDING, la llamada se completará. Este método usa más tiempo de CPU que los demás métodos descritos aquí.

  • APC. El cliente puede especificar una llamada de procedimiento asincrónico (APC) a la que se llama cuando se completa la llamada. Para ver el prototipo de la función APC, consulte RPCNOTIFICATION_ROUTINE. Se llama a APC con su parámetro Event establecido en RpcCallComplete. Para que las API se envíen, el subproceso de cliente debe estar en un estado de espera alertable.

    Si el campo hThread del identificador asincrónico se establece en 0, las API se ponen en cola en el subproceso que realizó la llamada asincrónica. Si no es cero, las API se ponen en cola en el subproceso especificado por m.

  • IOC. El puerto de finalización de E/S se notifica con los parámetros especificados en el identificador asincrónico. Para obtener más información, vea CreateIoCompletionPort.

  • Identificador de Windows. Se publica un mensaje en el identificador de ventana especificado (HWND).

En el fragmento de código siguiente se muestran los pasos esenciales necesarios para inicializar un identificador asincrónico y usarlo para realizar una llamada de procedimiento remoto asincrónico.

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 se muestra en este ejemplo, el programa cliente puede ejecutar llamadas a procedimientos remotos sincrónicos mientras una llamada de procedimiento asincrónico sigue pendiente. Este cliente crea un objeto de evento para que la biblioteca en tiempo de ejecución RPC la use para notificarlo cuando se complete la llamada asincrónica.

Nota

La notificación de finalización no se devolverá desde una rutina RPC asincrónica si se genera una excepción RPC durante una llamada asincrónica.