Compartir a través de


Envío de la respuesta asincrónica

Una vez completada la llamada asincrónica, el servidor envía una respuesta al cliente llamando a la función RpcAsyncCompleteCall y pasándole el identificador asincrónico. Esta llamada es necesaria incluso si la llamada asincrónica tiene un valor devuelto void y ningún parámetro [out]. Si la función tiene un valor devuelto, se pasa por referencia a RpcAsyncCompleteCall.

Cuando el servidor llama a RpcAsyncCompleteCall o RpcAsyncAbortCall, o se completa una llamada porque se produjo una excepción en la rutina del administrador del servidor, la biblioteca en tiempo de ejecución rpc destruye automáticamente el identificador asincrónico del servidor.

Nota

El servidor debe terminar de actualizar los parámetros [in, out] y [out] antes de llamar a RpcAsyncCompleteCall. No se pueden realizar cambios en esos parámetros ni en el identificador asincrónico después de llamar a RpcAsyncCompleteCall. Si se produce un error en la llamada a la función RpcAsyncCompleteCall , el tiempo de ejecución rpc libera los parámetros.

 

En el ejemplo siguiente se muestra una llamada de procedimiento asincrónico simple.

#define DEFAULT_ASYNC_DELAY 20;
#define ASYNC_CANCEL_CHECK 100;

void AsyncFunc(IN PRPC_ASYNC_STATE pAsync,
               IN RPC_BINDING_HANDLE hBinding,
               IN OUT unsigned long nAsychDelay)
{
    int nReply = 1;
    RPC_STATUS status;
    unsigned long nTmpAsychDelay;
    int i;
 
    if (nAsychDelay < 0){
        nAsychDelay = DEFAULT_ASYNC_DELAY;
    }else if (nAsychDelay < 100){
        nAsychDelay = 100;
    }

    // We only call RpcServerTestCancel if the call
    // takes longer than ASYNC_CANCEL_CHECK ms
    if(nAsychDelay > ASYNC_CANCEL_CHECK){
        
        nTmpAsychDelay = nAsychDelay/100;
 
        for (i = 0; i < 100; i++){
            Sleep(nTmpAsychDelay);
 
            if (i%5 == 0){
                fprintf(stderr, 
                        "\rRunning AsyncFunc (%lu ms) (%d%c) ... ",
                        nAsychDelay, i+5, PERCENT);
 
                status = 
                    RpcServerTestCancel(
                        RpcAsyncGetCallHandle(pAsync));
                if (status == RPC_S_OK){
                    fprintf(stderr, 
                            "\nAsyncFunc has been canceled!!!\n");
                    break;
                }else if (status != RPC_S_CALL_IN_PROGRESS){
                    printf(
                        "RpcAsyncInitializeHandle returned 0x%x\n", 
                        status);
                    exit(status); 
                }
            }
        }
    }else{
        Sleep(nAsychDelay);
    }
 
    printf("\nCalling RpcAsyncCompleteCall\n");
    status = RpcAsyncCompleteCall(pAsync, &nReply);
    printf("RpcAsyncCompleteCall returned 0x%x\n", status);
    if (status){
        exit(status);
    }
}

Por motivos de simplicidad, esta rutina de servidor asincrónica no procesa datos reales. Simplemente se pone a dormir por un tiempo.

Nota

Se puede llamar a la función RpcAsyncCompleteCall en el subproceso que recibió la llamada o en cualquier otro subproceso del proceso. Si todos los datos necesarios para completar la llamada están disponibles fácilmente, el servidor puede rellenarlos en el mismo subproceso y llamar a RpcAsyncCompleteCall en el mismo subproceso. Este enfoque guarda algún cambio de contexto y mejora el rendimiento. Estas llamadas se denominan asincrónicas oportunistamente.

 

RPC_ASYNC_STATE

RpcAsyncCompleteCall

RpcAsyncAbortCall

RpcServerTestCancel