다음을 통해 공유


비동기 호출 만들기

비동기 원격 호출을 만들려면 먼저 클라이언트가 비동기 핸들을 초기화해야 합니다. 클라이언트 및 서버 프로그램은 비동기 핸들에 RPC_ASYNC_STATE 구조체에 대한 포인터를 사용합니다.

모든 미해결 호출에는 고유한 비동기 핸들이 있어야 합니다. 클라이언트는 핸들을 만들고 RpcAsyncInitializeHandle 함수에 전달합니다. 호출이 올바르게 완료되도록 하려면 클라이언트는 핸들의 메모리가 서버의 비동기 회신을 받을 때까지 해제되지 않도록 해야 합니다. 또한 기존 비동기 핸들에서 다른 호출을 하기 전에 클라이언트가 핸들을 다시 초기화해야 합니다. 이렇게 하지 않으면 호출 중에 클라이언트 스텁이 예외를 발생시킬 수 있습니다. 또한 클라이언트는 [out] 매개 변수에 대해 제공하는 버퍼와 비동기 원격 프로시저 대한 매개 변수가 서버에서 회신을 받을 때까지 할당된 상태로 유지되도록 해야 합니다.

비동기 원격 프로시저를 호출할 때 클라이언트는 RPC 런타임 라이브러리가 호출 완료를 알리는 데 사용할 메서드를 선택해야 합니다. 클라이언트는 다음 방법 중 하나로 이 알림을 받을 수 있습니다.

  • 이벤트: 클라이언트는 호출이 완료될 때 발생할 이벤트를 지정할 수 있습니다. 자세한 내용은 이벤트 개체를 참조하세요.

  • 폴링 클라이언트는 RpcAsyncGetCallStatus를 반복적으로 호출할 수 있습니다. 반환 값이 RPC_S_ASYNC_CALL_PENDING 이외의 값이면 호출이 완료됩니다. 이 메서드는 여기에 설명된 다른 방법보다 더 많은 CPU 시간을 사용합니다.

  • Apc. 클라이언트는 호출이 완료되면 호출되는 APC(비동기 프로시저 호출) 를 지정할 수 있습니다. APC 함수의 프로토타입은 RPCNOTIFICATION_ROUTINE 참조하세요. APC는 Event 매개 변수를 RpcCallComplete로 설정하여 호출됩니다. APC가 디스패치되려면 클라이언트 스레드가 경고 가능한 대기 상태여야 합니다.

    비동기 핸들의 hThread 필드가 0으로 설정된 경우 APC는 비동기 호출을 수행한 스레드에서 큐에 대기합니다. 0이 아닌 경우 APC는 m으로 지정된 스레드에서 큐에 대기합니다.

  • Ioc. I/O 완료 포트는 비동기 핸들에 지정된 매개 변수를 사용하여 알림을 받습니다. 자세한 내용은 CreateIoCompletionPort를 참조하세요.

  • Windows 핸들. 지정된 창 핸들(HWND)에 메시지가 게시됩니다.

다음 코드 조각은 비동기 핸들을 초기화하고 이를 사용하여 비동기 원격 프로시저 호출을 만드는 데 필요한 필수 단계를 보여줍니다.

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

이 예제에서 알 수 있듯이 비동기 프로시저 호출이 아직 보류 중인 동안 클라이언트 프로그램은 동기 원격 프로시저 호출을 실행할 수 있습니다. 이 클라이언트는 비동기 호출이 완료되면 이를 알리는 데 사용할 RPC 런타임 라이브러리에 대한 이벤트 개체를 만듭니다.

참고

비동기 호출 중에 RPC 예외가 발생하는 경우 완료 알림은 비동기 RPC 루틴에서 반환되지 않습니다.