非同期関数のマネージャー ルーチンは、常に非同期ハンドルを最初のパラメーターとして受け取ります。 サーバーは、このハンドルを使用して応答を送信し、使用可能になったときに送信パイプ データを送信します。 ハンドルは、 RpcAsyncCompleteCall が呼び出されるか、 RpcAsyncAbortCall によって呼び出しが中止されるか、マネージャー ルーチンで例外が発生するまで有効です。 アプリケーションは、呼び出しを完了する前に更新するために、[out] パラメーターと [in, out] パラメーターのすべての最上位ポインターを追跡する必要があります。 また、アプリケーションは [in] パイプと [out] パイプも追跡する必要があります。
サーバーは、クライアントと同じ方法で非同期パイプ データを送信します。 「クライアント側の非同期パイプ処理」を参照してください。
サーバーは、クライアントと同じ方法で非同期パイプ データを受信します。 受信メカニズムが非同期プロシージャ 呼び出し (APC) の場合、サーバーはスレッド ハンドル (pAsync-u.APC.hThread>) を指定し、非同期ハンドルをランタイム ライブラリに登録する必要があります。
例
この例では、サーバー マネージャー ルーチン MyAsyncPipeFunc がクライアントからのリモート プロシージャ 呼び出しを処理します。
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++;
}
}
}
関連トピック