非同期応答の送信

非同期呼び出しが完了すると、サーバーは RpcAsyncCompleteCall 関数を呼び出して非同期ハンドルを渡すことによって、クライアントに応答を送信します。 この呼び出しは、非同期呼び出しに void 戻り値があり、[out] パラメーターがない場合でも必要です。 関数に戻り値がある場合は、 RpcAsyncCompleteCall への参照によって渡されます。

サーバーが RpcAsyncCompleteCall または RpcAsyncAbortCall を呼び出すか、サーバー マネージャー ルーチンで例外が発生したために呼び出しが完了すると、RPC ランタイム ライブラリによってサーバーの非同期ハンドルが自動的に破棄されます。

Note

サーバーは 、RpcAsyncCompleteCall を呼び出す前に、[in,out] パラメーターと [out] パラメーターの更新を完了する必要があります。 RpcAsyncCompleteCall を呼び出した後、これらのパラメーターや非同期ハンドルに変更を加えすることはできません。 RpcAsyncCompleteCall 関数呼び出しが失敗した場合、RPC ランタイムはパラメーターを解放します。

 

次の例は、単純な非同期プロシージャ呼び出しを示しています。

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

わかりやすくするために、この非同期サーバー ルーチンは実際のデータを処理しません。 それは単に少しの間眠りに自分自身を置きます。

Note

RpcAsyncCompleteCall 関数は、呼び出しを受信したスレッドまたはプロセス内の他のスレッドで呼び出すことができます。 呼び出しを完了するために必要なすべてのデータがすぐに使用できる場合は、サーバーが同じスレッドでデータを入力し、同じスレッドで RpcAsyncCompleteCall を 呼び出す可能性があります。 この方法では、コンテキストの切り替えを節約し、パフォーマンスを向上させます。 このような呼び出しは、日和見的に非同期と呼ばれます。

 

RPC_ASYNC_STATE

RpcAsyncCompleteCall

RpcAsyncAbortCall

RpcServerTestCancel