Durchführen des asynchronen Aufrufs

Bevor ein asynchroner Remoteaufruf durchgeführt werden kann, muss der Client das asynchrone Handle initialisieren. Client- und Serverprogramme verwenden Zeiger auf die RPC_ASYNC_STATE-Struktur für asynchrone Handles.

Jeder ausstehende Aufruf muss über ein eigenes eindeutiges asynchrones Handle verfügen. Der Client erstellt das Handle und übergibt es an die RpcAsyncInitializeHandle-Funktion . Damit der Aufruf ordnungsgemäß abgeschlossen wird, muss der Client sicherstellen, dass der Arbeitsspeicher für das Handle erst freigegeben wird, wenn die asynchrone Antwort des Servers empfangen wird. Außerdem muss der Client vor einem weiteren Aufruf eines vorhandenen asynchronen Handles das Handle neu initialisieren. Andernfalls löst der Client-Stub während des Aufrufs eine Ausnahme aus. Der Client muss auch sicherstellen, dass die Puffer, die er für [out]-Parameter und [in, out]-Parameter zu einer asynchronen Remoteprozedur bereitstellt, zugeordnet bleiben, bis er die Antwort vom Server empfangen hat.

Wenn eine asynchrone Remoteprozedur aufgerufen wird, muss der Client die Methode auswählen, die die RPC-Laufzeitbibliothek verwendet, um sie über den Abschluss des Aufrufs zu benachrichtigen. Der Client kann diese Benachrichtigung auf eine der folgenden Arten empfangen:

  • Ereignis Der Client kann angeben, dass ein Ereignis ausgelöst wird, wenn der Aufruf abgeschlossen ist. Weitere Informationen finden Sie unter Ereignisobjekte.

  • Abrufvorgang Der Client kann RpcAsyncGetCallStatus wiederholt aufrufen. Wenn der Rückgabewert nicht RPC_S_ASYNC_CALL_PENDING ist, ist der Aufruf abgeschlossen. Diese Methode verwendet mehr CPU-Zeit als die anderen hier beschriebenen Methoden.

  • APC. Der Client kann einen asynchronen Prozeduraufruf (APC) angeben, der nach Abschluss des Aufrufs aufgerufen wird. Den Prototyp der APC-Funktion finden Sie unter RPCNOTIFICATION_ROUTINE. Der APC wird aufgerufen, wobei der Event-Parameter auf RpcCallComplete festgelegt ist. Damit APCs verteilt werden, muss sich der Clientthread in einem warnbaren Wartezustand befinden.

    Wenn das Feld hThread im asynchronen Handle auf 0 festgelegt ist, werden die APCs in der Warteschlange in dem Thread eingereiht, der den asynchronen Aufruf ausgeführt hat. Wenn es ungleich null ist, werden die APCs in der Warteschlange in dem von m angegebenen Thread in die Warteschlange gestellt.

  • IOC. Der E/A-Vervollständigungsport wird mit den parametern benachrichtigt, die im asynchronen Handle angegeben sind. Weitere Informationen finden Sie unter CreateIoCompletionPort.

  • Windows-Handle. Eine Nachricht wird an das angegebene Fensterhandle (HWND) gesendet.

Das folgende Codefragment zeigt die wesentlichen Schritte, die zum Initialisieren eines asynchronen Handles und zum Ausführen eines asynchronen Remoteprozeduraufrufs erforderlich sind.

RPC_ASYNC_STATE Async;
RPC_STATUS status;
 
// Initialize the handle.
status = RpcAsyncInitializeHandle(&Async, sizeof(RPC_ASYNC_STATE));
if (status)
{
    // Code to handle the error goes here.
}
 
Async.UserInfo = NULL;
Async.NotificationType = RpcNotificationTypeEvent;
 
Async.u.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (Async.u.hEvent == 0)
{
    // Code to handle the error goes here.
}
// Call an asynchronous RPC routine here
RpcTryExcept
{
    printf("\nCalling the remote procedure 'AsyncFunc'\n");
    AsyncFunc(&Async, AsyncRPC_ClientIfHandle, nAsychDelay);
}
RpcExcept(1)
{
    ulCode = RpcExceptionCode();
    printf("AsyncFunc: Run time reported exception 0x%lx = %ld\n", 
            ulCode, ulCode);
}
RpcEndExcept
 
// Call a synchronous routine while
// the asynchronous procedure is still running
RpcTryExcept
{
    printf("\nCalling the remote procedure 'NonAsyncFunc'\n");
    NonAsyncFunc(AsyncRPC_ClientIfHandle, pszMessage);
    fprintf(stderr, 
            "While 'AsyncFunc' is running asynchronously,\n"
            "we still can send message to the server in the mean "
            "time.\n\n");
}
RpcExcept(1)
{
    ulCode = RpcExceptionCode();
    printf("NonAsyncFunc: Run time reported exception 0x%lx = %ld\n", 
            ulCode, ulCode);
}
RpcEndExcept

Wie in diesem Beispiel veranschaulicht, kann Ihr Clientprogramm synchrone Remoteprozeduraufrufe ausführen, während ein asynchroner Prozeduraufruf noch aussteht. Dieser Client erstellt ein Ereignisobjekt für die RPC-Laufzeitbibliothek, das verwendet wird, um sie zu benachrichtigen, wenn der asynchrone Aufruf abgeschlossen ist.

Hinweis

Die Benachrichtigung über den Abschluss wird von einer asynchronen RPC-Routine nicht zurückgegeben, wenn während eines asynchronen Aufrufs eine RPC-Ausnahme ausgelöst wird.