Dela via


Skicka det asynkrona svaret

När det asynkrona anropet är klart skickar servern ett svar till klienten genom att anropa funktionen RpcAsyncCompleteCall och genom att skicka det asynkrona handtaget. Det här anropet är nödvändigt även om det asynkrona anropet har ett ogiltigt returvärde och inga [out]-parametrar. Om funktionen har ett returvärde skickas den med referens till RpcAsyncCompleteCall.

När servern anropar RpcAsyncCompleteCall eller RpcAsyncAbortCall, eller ett anrop slutförs eftersom ett undantag uppstod i serverhanterarens rutin, förstör RPC-körningsbiblioteket automatiskt serverns asynkrona handtag.

Not

Servern måste slutföra uppdateringen av parametrarna [in, out] och [out] innan du anropar RpcAsyncCompleteCall. Inga ändringar kan göras i dessa parametrar eller i det asynkrona handtaget efter att du har anropat RpcAsyncCompleteCall. Om funktionsanropet RpcAsyncCompleteCall misslyckas, frigör RPC-programtiden parametrarna.

 

I följande exempel visas ett enkelt asynkront proceduranrop.

#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);
    }
}

För enkelhetens skull bearbetar inte den här asynkrona serverrutinen faktiska data. Den somnar helt enkelt för ett tag.

Notis

Funktionen RpcAsyncCompleteCall kan anropas antingen på tråden som tog emot anropet eller på någon annan tråd i processen. Om alla data som krävs för att slutföra anropet är lättillgängliga kan servern fylla i dem i samma tråd och anropa RpcAsyncCompleteCall- i samma tråd. Den här metoden sparar vissa kontextväxlingar och förbättrar prestandan. Sådana anrop kallas opportunistiskt asynkrona.

 

RPC_ASYNC_STATE

RpcAsyncCompleteCall

RpcAsyncAbortCall

RpcServerTestCancel