如何終止配接器
下列主題提供正確關閉配接器的指導。
終止配接器
當傳訊引擎關閉時,它會呼叫 IBTTransportControl。在每個進程內配接器上終止 。 在這個方法傳回之後,BizTalk Server 就會將配接器終結。 對於原生配接器而言,這項作業會立即發生,但對於 Managed 配接器來說,這項作業的發生時間就比較不明確,這是因為 .NET 記憶體回收程序使然。 配接器應該在 Terminate 中封鎖,並執行任何必要的清除工作,直到它準備好終結為止。
終止外掛式接收配接器
隔離接收配接器不會在它們上呼叫 Terminate ,因為它們未裝載于 BizTalk 服務中。 相反地,他們應該呼叫 IBTTransportProxy。TerminateIsolatedReceiver 通知傳訊引擎即將關閉。
使用 Marshal.ReleaseComObject 清除 COM 物件
在寫入使用 COM 物件的 Managed 程式碼時,Common Language Runtime (CLR) 會產生 Proxy 物件以保存 COM 物件的參考。 Proxy 物件是 Managed 物件,受記憶體回收的一般規則管制。 當記憶體回收行程只看到 .NET 執行階段所配置的記憶體,而不知道有 COM 物件存在時,就會發生問題。 因為 Proxy 物件所佔空間很小,所以當 CLR 記憶體回收行程不知道有它的存在時,就可能導致記憶體中保留了所佔空間很大的 COM 物件。
若要避免這個問題,請在完成時明確釋放基礎 COM 物件,特別是任何 IBTTransportBatch 物件。 您可以呼叫 封送處理來執行此動作。ReleaseComObject。
注意
ReleaseComObject 會傳回剩餘的參考數目,而且只有在這個傳回的值為零時,才會釋放 COM 物件。 ReleaseComObject通常會在迴圈中呼叫,以確保釋放物件。 完成後,您應該在此物件上呼叫 SuppressFinalize ,因為沒有任何專案可以完成。 最後一個步驟是檢查這是否真的是 COM 物件。
下列的程式碼顯示上述的程序:
if (Marshal.IsComObject (batch))
(
While (0 <Marshal.ReleaseComObject(batch)
;
GC.SuppressFinalize (batch);
明確釋放從GetBatch傳回的IBTTransportBatch物件,可能會大幅改善效能。
在關閉配接器時永遠使用終止
若要讓BizTalk Server將程式碼辨識為配接器,您必須實作稱為IBTTransportControl 的介面。 這個介面會定義 BizTalk Server 如何與您的配接器進行通訊,且定義如下:
public interface IBTTransportControl
{
void Initialize(IBTTransportProxy transportProxy);
void Terminate();
}
介面包含兩個方法 :Initialize 和 Terminate。
Initialize
BizTalk Server載入配接器元件之後呼叫Initialize方法。 這麼做可以將傳輸 Proxy (BizTalk Server 的主控點) 傳遞至配接器。 Initialize的實作只會將傳輸 Proxy 儲存在成員變數中。
Terminate
BizTalk Server在服務關機時呼叫Terminate方法,以提供配接器完成所有批次的執行時間。 這可讓 Terminate 方法的實作更加相關。
配接器在完成任何擱 置 的工作之前,不應該從 Terminate 呼叫傳回。 當BizTalk Server呼叫Terminate時,配接器應該嘗試停止其所有目前的工作,而不會啟動任何新的工作。
因為 終止 是在服務關機期間呼叫,所以如果配接器永久封鎖 在 Terminate中,服務控制管理員就會結束進程。 在這種情況下,服務控制管理員在停止 BizTalk Server 服務時會顯示警告訊息。 如有可能,請避免以這種方式永久地終止配接器。 如果配接器未正確地處理終止程序,而且在程序開始關閉時仍有執行緒在執行,則您可能會在關閉時偶爾看到發生 BizTalk Server 存取違規的情況。
因為這個 BizTalk Server 介面具有非同步的本質,所以在負載過低時可能會積存許多批次,因此造成仍有執行緒在執行中。 應該實作Terminate呼叫,以等候介面卡成功在BizTalk Server上執行的每個批次結束,再繼續進行。 批次結論是由來自 BizTalk Server 的BatchComplete回呼發出訊號。 Terminate呼叫應該等候每個擱置的BatchComplete發生。 不過,批次的執行必須成功才行。 也就是說, 對 IBTTransportBatch::Done 的呼叫不得失敗。 如果 IBTTransportBatch::Done 的呼叫失敗,則沒有批次回呼。
在瞭解您必須對配接器新增同步化程式碼之後,實作就相當簡單。
其中一個簡單方法是實作複合同步處理物件,其中包含 輸入 和 離開 背景工作執行緒的方法,以及 封鎖 執行緒時執行緒仍在受保護執行中的終止方法。 (,解決方案非常類似于熟悉的多讀取器、單一寫入器結構,其中背景工作執行緒可以視為讀取器,而 終止 方法則視為寫入器。)
terminate方法如下所示:
void terminate ()
{
this.control.Terminate();
}
對於每個工作者執行緒:
If (!this.control.Enter())
return; // we can’t enter because Terminate has been called
try
{
// create and fill batch
batch.Done();
}
catch (Exception)
{
// we are not expecting a callback
This.control.Leave();
}
在來自 BizTalk Server 的回呼中:
batchComplete (…)
{
// the callback from BizTalk Server
// process results
this.control.Leave();
}
BizTalk Server隨附基底配接器範例中的範例程式碼 ControlledTermination.cs,其中顯示此處所述的同步處理機制。