다음을 통해 공유


비동기 회신 대기 중

클라이언트가 서버로부터 회신 알림을 받기 위해 기다리는 동안 수행하는 작업은 선택한 알림 메커니즘에 따라 달라집니다.

클라이언트가 알림에 이벤트를 사용하는 경우 일반적으로 WaitForSingleObject 함수 또는 WaitForSingleObjectEx 함수를 호출합니다. 클라이언트는 이러한 함수 중 하나를 호출할 때 차단된 상태로 들어갑니다. 이는 클라이언트가 차단되는 동안 CPU 실행 주기를 사용하지 않기 때문에 효율적입니다.

폴링을 사용하여 결과를 기다리는 경우 클라이언트 프로그램은 RpcAsyncGetCallStatus 함수를 반복적으로 호출하는 루프를 입력합니다. 이는 클라이언트 프로그램이 폴링 루프에서 다른 처리를 수행하는 경우 대기하는 효율적인 방법입니다. instance 경우 후속 비동기 원격 프로시저 호출을 위해 작은 청크로 데이터를 준비할 수 있습니다. 각 청크가 완료되면 클라이언트가 미해결 비동기 원격 프로시저 호출을 폴링하여 완료되었는지 확인할 수 있습니다.

클라이언트 프로그램은 비동기 원격 프로시저 호출이 완료될 때 RPC 런타임 라이브러리가 호출할 콜백 함수의 형식인 APC(비동기 프로시저 호출)를 제공할 수 있습니다. 클라이언트 프로그램은 경고 대기 상태여야 합니다. 이는 일반적으로 클라이언트가 Windows API 함수를 호출하여 차단된 상태로 유지됨을 의미합니다. 자세한 내용은 비동기 프로시저 호출을 참조하세요.

참고

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

 

클라이언트 프로그램에서 I/O 완료 포트를 사용하여 완료 알림을 수신하는 경우 GetQueuedCompletionStatus 함수를 호출해야 합니다. 이렇게 하면 응답을 무기한 기다리거나 다른 처리를 계속할 수 있습니다. 회신을 기다리는 동안 다른 처리를 수행하는 경우 GetQueuedCompletionStatus 함수를 사용하여 완료 포트를 폴링해야 합니다. 이 경우 일반적으로 dwMilliseconds 를 0으로 설정해야 합니다. 이로 인해 비동기 호출이 완료되지 않은 경우에도 GetQueuedCompletionStatus 가 즉시 반환됩니다.

클라이언트 프로그램은 창 메시지 큐를 통해 완료 알림을 받을 수도 있습니다. 이 상황에서는 Windows 메시지와 마찬가지로 완료 메시지를 처리하기만 하면 됩니다.

다중 스레드 애플리케이션에서 호출을 시작한 스레드가 호출에서 성공적으로 반환된 후에만 클라이언트에서 비동기 호출을 취소할 수 있습니다. 이렇게 하면 동기 호출에 실패한 후 다른 스레드에서 호출이 비동기적으로 취소되지 않습니다. 표준 사례로 동기적으로 실패하는 비동기 호출은 비동기적으로 취소해서는 안 됩니다. 다른 스레드에서 호출을 실행하고 취소할 수 있는 경우 클라이언트 애플리케이션은 이 동작을 관찰해야 합니다. 또한 호출이 취소된 후 클라이언트 코드는 완료 알림을 기다린 후 호출을 완료해야 합니다. RpcAsyncCancelCall 함수는 단순히 완료 알림을 돌진합니다. 호출을 완료하는 대신 사용할 수 없습니다.

다음 코드 조각에서는 클라이언트 프로그램이 이벤트를 사용하여 비동기 회신을 기다리는 방법을 보여 줍니다.

// This code fragment assumes that Async is a valid asynchronous
// RPC handle.
if (WaitForSingleObject(Async.u.hEvent, INFINITE) == WAIT_FAILED)
{
    RpcRaiseException(APP_ERROR);
}

APC를 사용하여 비동기 회신 알림을 받는 클라이언트 프로그램은 일반적으로 차단된 상태로 전환됩니다. 다음 코드 조각은 이를 보여줍니다.

if (SleepEx(INFINITE, TRUE) != WAIT_IO_COMPLETION)
{
    RpcRaiseException(APP_ERROR);
}

이 경우 RPC 런타임 라이브러리가 APC를 호출할 때까지(표시되지 않음) 클라이언트 프로그램이 절전 모드로 이동하여 CPU 주기를 사용하지 않습니다.

다음 예제에서는 I/O 완료 포트를 사용하여 비동기 회신을 기다리는 클라이언트를 보여 줍니다.

// This code fragment assumes that Async is a valid asynchronous
// RPC handle.
if (!GetQueuedCompletionStatus(
         Async.u.IOC.hIOPort,
         &Async.u.IOC.dwNumberOfBytesTransferred,
         &Async.u.IOC.dwCompletionKey,
         &Async.u.IOC.lpOverlapped,
         INFINITE))
{
    RpcRaiseException(APP_ERROR);
}

앞의 예제에서 GetQueuedCompletionStatus 호출은 비동기 원격 프로시저 호출이 완료될 때까지 무기한 대기합니다.

다중 스레드 애플리케이션을 작성할 때 발생할 수 있는 문제 중 하나입니다. 스레드가 원격 프로시저 호출을 호출한 다음 보내기가 완료되었다는 알림을 받기 전에 종료되는 경우 원격 프로시저 호출이 실패하고 클라이언트 스텁이 서버에 대한 연결을 닫을 수 있습니다. 따라서 동작이 바람직하지 않을 때 호출이 완료되거나 취소되기 전에 원격 프로시저를 호출하는 스레드가 종료되지 않아야 합니다.