Senden der asynchronen Antwort
Wenn der asynchrone Aufruf abgeschlossen ist, sendet der Server eine Antwort an den Client, indem er die RpcAsyncCompleteCall-Funktion aufruft und ihr das asynchrone Handle übergibt. Dieser Aufruf ist auch dann erforderlich, wenn der asynchrone Aufruf über einen void-Rückgabewert und keine [out]-Parameter verfügt. Wenn die Funktion über einen Rückgabewert verfügt, wird sie als Verweis auf RpcAsyncCompleteCall übergeben.
Wenn der Server RpcAsyncCompleteCall oder RpcAsyncAbortCall aufruft oder ein Aufruf abgeschlossen wird, weil in der Server-Manager-Routine eine Ausnahme ausgelöst wurde, zerstört die RPC-Laufzeitbibliothek automatisch das asynchrone Handle des Servers.
Hinweis
Der Server muss die Aktualisierung der Parameter [in, out] und [out] abschließen, bevor RpcAsyncCompleteCall aufgerufen wird. Nach dem Aufruf von RpcAsyncCompleteCall können keine Änderungen an diesen Parametern oder am asynchronen Handle vorgenommen werden. Wenn der RpcAsyncCompleteCall-Funktionsaufruf fehlschlägt, gibt die RPC-Runtime die Parameter frei.
Das folgende Beispiel veranschaulicht einen einfachen asynchronen Prozeduraufruf.
#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);
}
}
Der Einfachheit halber verarbeitet diese asynchrone Serverroutine keine tatsächlichen Daten. Es legt sich einfach eine Weile in den Schlaf.
Hinweis
Die RpcAsyncCompleteCall-Funktion kann entweder für den Thread aufgerufen werden, der den Aufruf empfangen hat, oder für jeden anderen Thread im Prozess. Wenn alle zum Abschließen des Aufrufs erforderlichen Daten verfügbar sind, füllt der Server sie möglicherweise im selben Thread aus und ruft rpcAsyncCompleteCall im selben Thread auf. Dieser Ansatz spart einige Kontextwechsel und verbessert die Leistung. Solche Aufrufe werden opportunistisch asynchron genannt.
Zugehörige Themen