共用方式為


通知通道

本節包含 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. 交談篩選準則。 呼叫端必須指定這是否為單向通道或雙向通道。 若要將通道標示為單向,請將IPrintAsyncNotifyChannel**類型 (的最後一個參數設定為Null ) CreatePrintAsyncNotifyChannel

  5. 當通知從通道的另一端傳回時,要呼叫的 IPrintAsyncNotifyCallback 介面。 如果呼叫端對接收回應不感興趣,這可以是 Null

CreatePrintAsyncNotifyChannel 傳回時, IPrintAsyncNotifyChannel**類型 (的第六個參數) 指向包含 IPrintAsyncNotifyChannel 物件的位址的記憶體位置。 此物件會識別通道,並用來傳送通知並關閉通道。

IPrintAsyncNotifyChannel 介面

IPrintAsyncNotifyChannel介面會識別通道,並用來傳送通知並關閉通道。 當列印元件呼叫 CreatePrintAsyncNotifyChannel 函式來建立通知通道時,多工緩衝處理常式服務會提供公開 IPrintAsyncNotifyChannel 介面的物件來回應。

這個介面繼承自 IUnknown 介面,讓多工緩衝處理常式通知機制的用戶端可以實作 COM 或 C++ 物件。 下列程式碼範例中的介面宣告會顯示此繼承:

#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 指標。 關閉通道時,會捨棄所有已排入佇列的通知。

您必須小心在通道物件上呼叫 Release ,因為它不會遵循所有一般 COM 程式設計不變數。 只有在發生下列情況時,才應該在IPrintAsyncNotifyChannel上呼叫Release

  • 如果您明確呼叫 AddRef ,而且您必須與 Release的呼叫相符。

  • 如果您將通道建立為單向通道,則必須在您收到的指標上呼叫 Release 一次作為輸出參數。 您應該在傳送所需的通知並關閉通道之後呼叫 Release

  • 如果您將通道建立為雙向,您可能必須在您收到作為輸出參數的指標上呼叫 Release 一次。 只有在執行下列一或多個動作時,才應該呼叫 Release

    • 呼叫雙向通道的 Release 之前,您一律必須呼叫 CloseChannel 並收到成功結果。 如果CloseChannel的呼叫失敗,您就不得呼叫Release,因為通道可能已代表您發行。

    • 輸入ChannelClosed事件時,您不得呼叫Release。 若要避免這種情況,請檢查已失敗的 CloseChannel 呼叫,並CHANNEL_ALREADY_CLOSED錯誤。 在此情況下,您不需要呼叫 Release ,因為通道已代表您發行。

    • 如果您的ChannelClosed回呼函式已完成執行,您就不得呼叫通道上的CloseChannelRelease或任何其他成員函式。 在此情況下,通道已經釋放,因此任何進一步的呼叫都可能會導致未定義的行為。 此限制可能需要在前景執行緒和回呼物件之間進行協調。

    • 您必須確定前景執行緒和回呼物件會協調 CloseChannelRelease的呼叫。 如果另一個執行緒即將呼叫或已完成呼叫Release,則前景執行緒和回呼物件無法開始對CloseChannel的呼叫。 您可以使用 InterlockedCompareExchange 常式來實作此限制。 如果您未使用 InterlockedCompareExchange,可能會造成未定義的行為。

  • 如果您在通道上註冊為接聽程式,您可以呼叫CloseChannel,然後在IPrintAsyncNotifyCallback::OnEventNotify回呼函式中呼叫Release以結束雙向通訊。 不過,您不得在ChannelClosed回呼中呼叫CloseChannelRelease

如果您符合上述其中一個條件,您必須呼叫 Release。 如果您不符合上述其中一個條件,則不得呼叫 Release

注意

在任何上述條件下呼叫 Release ,但第一個條件明確呼叫 AddRef ,是一般 COM 程式設計模式的例外狀況。 IPrintAsyncNotifyChannel 與在此情況下的標準 COM 做法不同。