Partager via


Réalisation de l’appel asynchrone

Avant d’effectuer un appel à distance asynchrone, le client doit initialiser le handle asynchrone. Les programmes client et serveur utilisent des pointeurs vers la structure RPC_ASYNC_STATE pour les handles asynchrones.

Chaque appel en attente doit avoir son propre handle asynchrone unique. Le client crée le handle et le transmet à la fonction RpcAsyncInitializeHandle . Pour que l’appel se termine correctement, le client doit s’assurer que la mémoire du handle n’est pas libérée tant qu’il n’a pas reçu la réponse asynchrone du serveur. En outre, avant d’effectuer un autre appel sur un handle asynchrone existant, le client doit réinitialiser le handle. Si vous ne le faites pas, le stub du client génère une exception pendant l’appel. Le client doit également s’assurer que les mémoires tampons qu’il fournit pour les paramètres [out] et les paramètres [in, out] à une procédure distante asynchrone restent alloués jusqu’à ce qu’il ait reçu la réponse du serveur.

Lorsqu’il appelle une procédure distante asynchrone, le client doit sélectionner la méthode que la bibliothèque d’exécution RPC utilisera pour l’informer de la fin de l’appel. Le client peut recevoir cette notification de l’une des manières suivantes :

  • Événement. Le client peut spécifier un événement à déclencher une fois l’appel terminé. Pour plus d’informations, consultez Event Objects.

  • Interrogation. Le client peut appeler à plusieurs reprises RpcAsyncGetCallStatus. Si la valeur de retour est autre que RPC_S_ASYNC_CALL_PENDING, l’appel est terminé. Cette méthode utilise plus de temps processeur que les autres méthodes décrites ici.

  • APC. Le client peut spécifier un appel de procédure asynchrone (APC) qui est appelé à la fin de l’appel. Pour le prototype de la fonction APC, consultez RPCNOTIFICATION_ROUTINE. L’APC est appelé avec son paramètre d’événement défini sur RpcCallComplete. Pour que les API soient distribués, le thread client doit être dans un état d’attente pouvant être alerté.

    Si le champ hThread dans le handle asynchrone a la valeur 0, les API sont mis en file d’attente sur le thread qui a effectué l’appel asynchrone. S’il n’est pas nul, les API sont mis en file d’attente sur le thread spécifié par m.

  • CIO. Le port d’achèvement des E/S est averti avec les paramètres spécifiés dans le handle asynchrone. Pour plus d’informations, consultez CreateIoCompletionPort.

  • Handle Windows. Un message est publié dans le handle de fenêtre spécifié (HWND).

Le fragment de code suivant montre les étapes essentielles requises pour initialiser un handle asynchrone et l’utiliser pour effectuer un appel de procédure distante asynchrone.

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

Comme le montre cet exemple, votre programme client peut exécuter des appels de procédure distante synchrone alors qu’un appel de procédure asynchrone est toujours en attente. Ce client crée un objet d’événement que la bibliothèque d’exécution RPC doit utiliser pour l’avertir lorsque l’appel asynchrone se termine.

Notes

La notification d’achèvement ne sera pas retournée à partir d’une routine RPC asynchrone si une exception RPC est levée pendant un appel asynchrone.