使用 Impl 方法進行同步或非同步輸出 (POS for .NET v1.14 SDK 文件)
某些 POS 裝置類型支援列印或顯示輸出,例如 PosPrinter 或 LineDisplay。 針對啟用輸出裝置所撰寫的服務物件應該同時支援非同步與同步輸出。
執行非同步作業的應用程式,會在呼叫所需的輸出方法之前,將 Service 物件的 AsyncMode 屬性設定為 true。 如果 Service 物件無法以非同步方式處理請求,可能會以例外狀況擲回,但這不是理想狀況,因為它會限制可能使用特定 Service 物件的應用程式範圍。
不過,支援非同步輸出可能需要額外且可能很複雜的程式碼。 此程式碼會管理傳入請求的佇列、維護執行緒,以適當順序監視佇列與分派請求,並將事件傳回應用程式。
Microsoft Point of Service for .NET (POS for .NET) 基底類別可以管理開發人員的所有工作。 針對每個輸出方法,基底類別都有與每個輸出方法相關聯的協助程式方法。 這些以 Impl 尾碼結尾的方法,會撰寫成如同只是其父代方法的同步導入。 基底類別以透明的方式管理佇列、在正確的時間以正確的順序將請求分派至 Impl 函式,並將適當的事件傳回應用程式。 同步與非同步作業都會呼叫這個相同方法。
衍生自 POS for .NET 基底類別,服務物件會取得非同步功能,而不導入其他程式碼。
基底類別導入
POS for .NET 提供 POS 裝置類型子集的基底類別 。 這些類別的每個輸出方法都有一個對應方法,其包含 Impl 尾碼。 衍生自基底類別的服務物件應該只覆寫 Impl 方法,而不是對應的父代方法。 例如,在衍生自 POS for .NET 基底的類別 PosPrinterBase,服務物件會提供 PrintNormalImpl 的導入,而且不會覆寫 PrintNormal。
POS for .NET 基底類別會導入所有輸出方法,並執行下列工作,以支援服務物件導入的 Impl 方法:
- 驗證引數。
- 如果 AsyncMode 屬性為 false,則會立即呼叫對應的 Impl 方法。
- 如果 AsyncMode 屬性設定為 true:
- 請求會放在佇列。 此佇列由 POS for .NET 擁有,並由其本身的執行緒管理。
- 佇列執行緒會檢查排入佇列的請求,並呼叫對應的 Impl 方法。 如果裝置已經處理輸出請求,或佇列具有優先順序較高的請求,此呼叫可能會延遲。
- 當 Impl 方法傳回時,POS for .NET 基底類別程式碼會處理所有結果。 針對同步呼叫,方法可能會傳回值或擲回例外狀況。 針對非同步呼叫,方法可能會將 OutputCompleteEvent 或 ErrorEvent 事件傳回應用程式。
- Impl 方法也可以傳回物件,其不僅包含錯誤資訊,也包含統計資料值。
Service 物件 Impl 方法
由於大部分的處理都是由基底類別程式碼處理,因此 Service Object 的 Impl 方法可能相對簡單。
在許多情況下,Impl方法需要在原始呼叫時裝置的狀態。 在這些情況下,基底類別程式碼會順應輸出請求儲存目前的裝置狀態。 裝置狀態稍後會以 Impl 方法的引數傳送。 例如,PrintNormalImpl 的定義是:
protected override PrintResults PrintNormalImpl(
PrinterStation station,
PrinterState printerState,
string data);
上述引數 printerState 是 Impl 方法特有的,而且不存在於定義 PrintNormal(PrinterStation, String)。
Impl 函式的傳回值也與其呼叫方法不同。 例如,請注意,PrintNormalImpl 方法會傳回 PrintResults 類型的類別。 除了 ErrorCode、ErrorCodeExtended、ErrorLevel 與 ErrorString之外,呼叫方法還會使用一些其他屬性來更新統計資料計數。
範例
下列範例示範如何在 Service 物件程式碼導入這些方法。
protected override PrintResults PrintNormalImpl(
PrinterStation station,
PrinterState printerState,
string data)
{
// First, create a PrintResults object to hold return values.
PrintResults pr = new PrintResults();
// Now print, depending on the station.
if (station == PrinterStation.Receipt)
{
// Your code goes here.
// Update statistics to be returned to the caller.
pr.ReceiptLinePrintedCount = 1;
pr.ReceiptCharacterPrintedCount = data.Length;
}
else if (station == PrinterStation.Slip)
{
// Your code goes here.
// Update statistics to be returned to the caller.
pr.SlipLinePrintedCount = 1;
pr.SlipCharacterPrintedCount = data.Length;
}
return pr;
}