发送异步答复

异步调用完成后,服务器通过调用 RpcAsyncCompleteCall 函数并向其传递异步句柄,向客户端发送答复。 即使异步调用具有 void 返回值且没有 [out] 参数,此调用也是必需的。 如果该函数具有返回值,则它通过引用传递给 RpcAsyncCompleteCall

当服务器调用 RpcAsyncCompleteCallRpcAsyncAbortCall 时,或者由于服务器管理器例程中引发异常而完成调用时,RPC 运行时库会自动销毁服务器的异步句柄。

注意

在调用 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);
    }
}

为简单起见,此异步服务器例程不处理实际数据。 它只是让自己睡了一会儿。

注意

RpcAsyncCompleteCall 函数可以在接收调用的线程上调用,也可以在进程中的任何其他线程上调用。 如果完成调用所需的所有数据都随时可用,服务器可以在同一线程上填充这些数据,并在同一线程上调用 RpcAsyncCompleteCall 。 此方法可节省一些上下文切换并提高性能。 此类调用称为机会异步调用。

 

RPC_ASYNC_STATE

RpcAsyncCompleteCall

RpcAsyncAbortCall

RpcServerTestCancel