알림 채널

이 섹션에는 CreatePrintAsyncNotifyChannel 함수 및 IPrintAsyncNotifyChannel 인터페이스에 대한 정보가 포함되어 있습니다.

HRESULT
 CreatePrintAsyncNotifyChannel(
    IN LPCWSTR,
    IN PrintAsyncNotificationType*,
    IN PrintAsyncNotifyUserFilter,
    IN PrintAsyncNotifyConversationStyle,
    IN IPrintAsyncNotifyCallback*,
 OUT IPrintAsyncNotifyChannel**
    );

인쇄 구성 요소는 CreatePrintAsyncNotifyChannel 함수를 호출하여 알림 채널을 만듭니다. 채널은 프린터당 또는 서버당일 수 있습니다.

스풀러에서 구성 요소를 로드하는 경우에만 인쇄 구성 요소가 알림 채널을 열 수 있습니다. Winspool.drv는 호출자가 스풀러 서비스가 아닌 애플리케이션 내에서 실행되는 경우 이 기능을 사용하지 않도록 설정합니다. 예를 들어 애플리케이션이 렌더링을 수행하기 위해 드라이버를 로드하면 CreatePrintAsyncNotifyChannel 호출이 실패합니다. 그러나 스풀러 서비스에서 드라이버를 로드하면 동일한 호출이 성공합니다.

Spoolss.lib는 포트 모니터가 채널을 열 수 있도록 이 기능을 제공합니다. 스풀러 내에서 실행되고 Spoolss.lib에 연결된 구성 요소는 CreatePrintAsyncNotifyChannel 함수를 호출할 수 있습니다. 다음 절차에서는 이 함수에 대한 호출에서 각 입력 매개 변수의 용도를 설명합니다. 프로시저의 첫 번째 단계는 이 함수의 첫 번째 매개 변수에 적용되고 두 번째 단계는 두 번째 매개 변수에 적용됩니다.

알림 채널을 만들려면 다음 항목을 지정합니다.

  1. 프린터 또는 서버의 이름입니다.

  2. 알림 채널 유형입니다. 호출자는 이 채널을 통해 보낼 알림 유형을 지정할 수 있습니다.

  3. 사용자 필터입니다. 호출자는 알림을 받을 사용자, 알림 발신자와 동일한 사용자 또는 모든 사용자를 지정할 수 있습니다.

  4. 대화 필터입니다. 호출자는 이 채널이 단방향 채널인지 양방향 채널인지를 지정해야 합니다. 채널을 단방향으로 표시하려면 CreatePrintAsyncNotifyChannel의 마지막 매개 변수(IPrintAsyncNotifyChannel**형식)를 NULL로 설정합니다.

  5. 알림이 채널의 다른 쪽 끝에서 돌아올 때 호출할 IPrintAsyncNotifyCallback 인터페이스입니다. 호출자가 응답을 받는 데 관심이 없는 경우 NULL일 수 있습니다.

CreatePrintAsyncNotifyChannel이 반환되면 여섯 번째 매개 변수(IPrintAsyncNotifyChannel**형식)는 IPrintAsyncNotifyChannel 개체 의 주소가 포함된 메모리 위치를 가리킵니다. 이 개체는 채널을 식별하고 알림을 보내고 채널을 닫는 데 사용됩니다.

IPrintAsyncNotifyChannel 인터페이스

IPrintAsyncNotifyChannel 인터페이스는 채널을 식별하고 알림을 보내고 채널을 닫는 데 사용됩니다. 인쇄 구성 요소가 CreatePrintAsyncNotifyChannel 함수를 호출하여 알림 채널을 만들면 스풀러 서비스는 IPrintAsyncNotifyChannel 인터페이스를 노출하는 개체를 제공하여 응답합니다.

이 인터페이스는 스풀러 알림 메커니즘의 클라이언트가 COM 또는 C++ 개체를 구현할 수 있도록 IUnknown 인터페이스에서 상속됩니다. 다음 코드 예제의 인터페이스 선언은 이 상속을 보여줍니다.

#define INTERFACE IPrintAsyncNotifyChannel
DECLARE_INTERFACE_(IPrintAsyncNotifyChannel, IUnknown)
{
    STDMETHOD(QueryInterface)(
        THIS_
        REFIID riid,
        void** ppvObj
        ) PURE;

    STDMETHOD_(ULONG, AddRef)(
        THIS
        ) PURE;

    STDMETHOD_(ULONG, Release)(
        THIS
        ) PURE;

    STDMETHOD(SendNotification)(
         THIS_
         IN IPrintAsyncNotifyDataObject*
         ) PURE;

    STDMETHOD(CloseChannel)(
         THIS_
         IN IPrintAsyncNotifyDataObject*
         ) PURE;
};

알림을 보내기 위해 발신자는 IPrintAsyncNotifyChannel::SendNotification 메서드를 호출합니다. 발신자는 채널을 열고 알림을 보내는 인쇄 구성 요소이거나 알림에 응답해야 할 때 수신 대기 클라이언트일 수 있습니다. 이 메서드는 비동기적으로 동작합니다. 메서드가 성공 코드를 반환하면 스풀러는 수신기에 알림을 보내려고 시도합니다. 그러나 수신기가 알림을 받는다는 보장은 없습니다.

채널을 닫기 위해 발신자 또는 수신기는 IPrintAsyncNotifyChannel::CloseChannel 메서드를 호출할 수 있습니다. 호출자는 채널을 닫는 이유를 제공하거나 NULL 포인터를 전달할 수 있는 알림을 전달할 수 있습니다. 채널이 닫혀 있으면 대기 중인 모든 알림이 삭제됩니다.

채널 개체가 모든 일반 COM 프로그래밍 고정을 따르지 않으므로 채널 개체에서 Release 를 호출하는 데 주의해야 합니다. 다음 조건이 발생하는 경우에만 IPrintAsyncNotifyChannel에서 Release를 호출해야 합니다.

  • AddRef를 명시적으로 호출한 경우 릴리스 호출과 일치해야 합니다.

  • 채널을 단방향으로 만든 경우 출력 매개 변수로 받은 포인터에서 Release 를 한 번 호출해야 합니다. 원하는 알림을 보내고 채널을 닫은 후에 릴리스 를 호출해야 합니다.

  • 채널을 양방향으로 만든 경우 출력 매개 변수로 받은 포인터에서 릴리스 를 한 번 호출해야 할 수 있습니다. 다음 중 하나 이상을 수행하는 경우에만 Release 를 호출해야 합니다.

    • 양방향 채널에 대해 Release 를 호출하기 전에 항상 CloseChannel 을 호출하고 성공 결과를 받아야 합니다. 채널이 사용자를 대신하여 이미 릴리스되었을 수 있으므로 CloseChannel에 대한 호출이 실패하는 경우 Release를 호출하지 않아야 합니다.

    • ChannelClosed 이벤트를 입력하는 동안에는 Release를 호출하면 안 됩니다. 이 상황을 방지하려면 오류 CHANNEL_ALREADY_CLOSED 실패한 CloseChannel에 대한 호출을 검사. 채널이 사용자를 대신하여 이미 릴리스되었기 때문에 이 경우 릴리스 를 호출할 필요가 없습니다.

    • ChannelClosed 콜백 함수의 실행이 완료된 경우 채널에서 CloseChannel, Release 또는 기타 멤버 함수를 호출해서는 안 됩니다. 이 경우 채널이 이미 릴리스되었으므로 추가 호출로 인해 정의되지 않은 동작이 발생할 수 있습니다. 이 제한을 사용하려면 포그라운드 스레드와 콜백 개체 간의 조정이 필요할 수 있습니다.

    • 포그라운드 스레드와 콜백 개체가 CloseChannelRelease에 대한 호출을 조정하는지 확인해야 합니다. 포그라운드 스레드와 콜백 개체는 다른 스레드가 호출하려고 하거나 Release 호출을 완료한 경우 CloseChannel에 대한 호출을 시작할 수 없습니다. InterlockedCompareExchange 루틴을 사용하여 이 제한을 구현할 수 있습니다. InterlockedCompareExchange를 사용하지 않으면 정의되지 않은 동작이 발생할 수 있습니다.

  • 채널에서 수신기로 등록한 경우 CloseChannel을 호출한 다음 IPrintAsyncNotifyCallback::OnEventNotify 콜백 함수에서 Release를 호출하여 양방향 통신을 종료할 수 있습니다. 그러나 ChannelClosed 콜백에서 CloseChannel 또는 Release를 호출해서는 안 됩니다.

이러한 조건 중 하나를 충족하는 경우 Release를 호출해야 합니다. 이러한 조건 중 하나를 충족하지 않는 경우 Release를 호출하면 안 됩니다.

참고

이전 조건 중에서 릴리스 를 호출하지만, AddRef 를 명시적으로 호출하는 첫 번째 조건은 일반적인 COM 프로그래밍 패턴에 대한 예외입니다. IPrintAsyncNotifyChannel 은 이 상황에서 표준 COM 사례와 다릅니다.