Envoi de la réponse asynchrone
Une fois l’appel asynchrone terminé, le serveur envoie une réponse au client en appelant la fonction RpcAsyncCompleteCall et en lui transmettant le handle asynchrone. Cet appel est nécessaire même si l’appel asynchrone a une valeur de retour void et aucun paramètre [out]. Si la fonction a une valeur de retour, elle est passée par référence à RpcAsyncCompleteCall.
Lorsque le serveur appelle RpcAsyncCompleteCall ou RpcAsyncAbortCall, ou qu’un appel se termine parce qu’une exception a été déclenchée dans la routine du gestionnaire de serveur, la bibliothèque runtime RPC détruit automatiquement le handle asynchrone du serveur.
Notes
Le serveur doit terminer la mise à jour des paramètres [in, out] et [out] avant d’appeler RpcAsyncCompleteCall. Aucune modification ne peut être apportée à ces paramètres ou au handle asynchrone après l’appel de RpcAsyncCompleteCall. Si l’appel de fonction RpcAsyncCompleteCall échoue, le runtime RPC libère les paramètres.
L’exemple suivant illustre un appel de procédure asynchrone simple.
#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);
}
}
Par souci de simplicité, cette routine de serveur asynchrone ne traite pas les données réelles. Il se met simplement à dormir pendant un certain temps.
Notes
La fonction RpcAsyncCompleteCall peut être appelée soit sur le thread qui a reçu l’appel, soit sur tout autre thread du processus. Si toutes les données nécessaires à l’exécution de l’appel sont facilement disponibles, le serveur peut les remplir sur le même thread et appeler RpcAsyncCompleteCall sur le même thread. Cette approche permet d’économiser certains changements de contexte et d’améliorer les performances. Ces appels sont appelés asynchrones de manière opportuniste.
Rubriques connexes