Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
После завершения асинхронного вызова сервер отправляет клиенту ответ, вызвав функцию RpcAsyncCompleteCall и передав ей асинхронный дескриптор. Этот вызов необходим, даже если асинхронный вызов имеет возвращаемое значение void и нет параметров [out]. Если функция имеет возвращаемое значение, она передается по ссылке на RpcAsyncCompleteCall.
Когда сервер вызывает RpcAsyncCompleteCall или RpcAsyncAbortCall, или если вызов завершается из-за возникновения исключения в подпрограмме диспетчера сервера, библиотека времени выполнения RPC автоматически уничтожает асинхронный дескриптор сервера.
Заметка
Сервер должен завершить обновление параметров [in, out] и [out] перед вызовом RpcAsyncCompleteCall. После вызова 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 в одном потоке. Этот подход уменьшает количество переключений контекста и повышает производительность. Такие вызовы называются оппортунистически асинхронными.
Связанные разделы