傳送非同步回復

非同步呼叫完成時,伺服器會呼叫 RpcAsyncCompleteCall 函式並將它傳遞至非同步控制碼,以傳送回復給用戶端。 即使非同步呼叫具有 void 傳回值且沒有 [out] 參數,這個呼叫也是必要的。 如果函式有傳回值,則會以 RpcAsyncCompleteCall的參考傳遞。

當伺服器呼叫 RpcAsyncCompleteCallRpcAsyncAbortCall或呼叫完成時,因為伺服器管理員常式中引發例外狀況,RPC 執行時間程式庫會自動終結伺服器的非同步控制碼。

注意

伺服器必須先完成更新 [in, out] 和 [out] 參數,才能呼叫 RpcAsyncCompleteCall。 呼叫 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);
    }
}

為了簡單起見,這個非同步伺服器常式不會處理實際資料。 它只會讓本身進入睡眠狀態一段時間。

注意

RpcAsyncCompleteCall函式可以在接收呼叫的執行緒上呼叫,或在進程中的任何其他執行緒上呼叫。 如果完成呼叫所需的所有資料都已就緒,伺服器可能會填入相同的執行緒,並在相同的執行緒上呼叫 RpcAsyncCompleteCall 。 此方法會儲存一些內容切換並改善效能。 這類呼叫會以非同步方式呼叫。

 

RPC_ASYNC_STATE

RpcAsyncCompleteCall

RpcAsyncAbortCall

RpcServerTestCancel