Gestione della pipe asincrona lato server
La routine di gestione di una funzione asincrona riceve sempre l'handle asincrono come primo parametro. Il server usa questo handle per inviare la risposta e inviare i dati della pipe out man mano che diventano disponibili. L'handle rimane valido finché non viene chiamato RpcAsyncCompleteCall , la chiamata viene interrotta da RpcAsyncAbortCall o si verifica un'eccezione nella routine di gestione. L'applicazione deve tenere traccia di tutti i puntatori di primo livello per i parametri [out] e [in, out] per aggiornarli prima di completare la chiamata. L'applicazione deve anche tenere traccia delle pipe [in] e [out].
Il server invia i dati della pipe asincrona nello stesso modo del client. Vedere Gestione asincrona lato client.
Il server riceve i dati della pipe asincrona nello stesso modo del client. Se il meccanismo di ricezione è chiamate di routine asincrone , il server deve specificare un handle di thread (in pAsync-u.APC.hThread>) e registrare l'handle asincrono con la libreria di runtime.
Esempio
In questo esempio, la routine server manager, MyAsyncPipeFunc, gestisce la chiamata di procedura remota dal client.
typedef struct
{
PRPC_ASYNC_STATE pAsync;
ASYNC_INTPIPE *inpipe;
ASYNC_INTPIPE *outpipe;
int i;
int *b;
int PipeBuffer[ASYNC_CHUNK_SIZE];
} PIPE_CALL_COOKIE;
void MyAsyncPipeFunc(
IN PRPC_ASYNC_STATE pAsync,
IN RPC_BINDING_HANDLE hBinding,
IN int a,
IN ASYNC_INTPIPE *inpipe,
OUT ASYNC_INTPIPE *outpipe,
OUT int *b)
{
unsigned long ThreadIdentifier;
HANDLE HandleToThread;
PIPE_CALL_COOKIE *PipeCallCookie;
PipeCallCookie = new PIPE_CALL_COOKIE;
PipeCallCookie->pAsync = pAsync;
PipeCallCookie->inpipe = inpipe;
PipeCallCookie->outpipe = outpipe;
PipeCallCookie->b = b;
pAsync->u.APC.hThread = 0;
pAsync->u.APC.hThread = CreateThread(
0, DefaultThreadStackSize,
(LPTHREAD_START_ROUTINE)
ThreadProcPipes,
PipeCallCookie, 0,
&ThreadIdentifier);
}// endMyAsyncPipeFunc
//Sending pipe data
//This APC routine is called when a pipe send completes,
//or when an asynchronous call completes.
//This thread routine receives pipe data, processes the call,
//sends the reply back to the client, and
//completes the asynchronous call.
void ThreadProcPipes(IN PIPE_CALL_COOKIE *Cookie)
{
int *ptr ;
int n ;
int retval ;
while (pAsync->u.APC.hThread == 0)
{
Sleep(10);
}
pAsync->Flags = RPC_C_NOTIFY_ON_SEND_COMPLETE;
pAsync->UserInfo = (void *) PipeCallCookie;
pAsync->NotificationType = RpcNotificationTypeApc;
pAsync->u.APC.NotificationRoutine = MyAsyncPipeAPCRoutine;
pAsync->u.APC.hThread = HandleToThread;
RpcAsyncRegisterHandle(pAsync);
while (!fDone)
{
Cookie->inpipe->pull(
Cookie->inpipe.state,
(int *) Cookie->PipeBuffer,
ASYNC_CHUNK_SIZE,
&num_elements);
switch (Status)
{
case RPC_S_ASYNC_CALL_PENDING:
if (SleepEx(INFINITE, TRUE) != WAIT_IO_COMPLETION)
{
RpcRaiseException(APP_ERROR) ;
}
break;
case RPC_S_OK:
if (num_elements == 0)
{
fDone = 1;
}
else
{
// process the received data
}
break;
default:
fDone = 1;
break;
}
}
Cookie->i = 1;
Cookie->outpipe->push(
Cookie->outpipe.state,
0,
Cookie->PipeBuffer,
ASYNC_CHUNK_SIZE) ;
while (Cookie->i < ASYNC_NUM_CHUNKS+1)
{
if (SleepEx(INFINITE, TRUE) != WAIT_IO_COMPLETION)
{
RpcRaiseException (APP_ERROR);
}
}
// sending non pipe reply
*(Cookie->b) = 10;
Status = RpcAsyncCompleteCall (Cookie->pAsync, &retval);
}
void MyAsyncPipeAPCRoutine (
IN PRPC_ASYNC_STATE pAsync,
IN void *Context,
IN unsigned int Flags)
{
PIPE_CALL_COOKIE *Cookie = (PIPE_CALL_COOKIE *) pAsync->UserInfo;
if (Flags & RPC_ASYNC_PIPE_SEND_COMPLETE)
{
if (Cookie->i & ASYNC_NUM_CHUNKS)
{
Cookie->outpipe->push(
Cookie->outpipe.state,
0,
(int *) Cookie->PipeBuffer,
ASYNC_CHUNK_SIZE);
Cookie->i++ ;
}
else
{
pAsync->Flags = 0;
Cookie->outpipe->push(Cookie->outpipe.state, 0, 0, 0);
Cookie->i++;
}
}
}
Argomenti correlati