Share via


Beenden eines Adapters

Die folgenden Themen enthalten Anleitungen zum sachgemäßen Beenden eines Adapters.

Beenden eines Adapters

Wenn die Messaging-Engine heruntergefahren wird, ruft sie IBTTransportControl auf. Beenden Sie jeden In-Prozess-Adapter. Nach dem Ausführen dieser Methode löscht BizTalk Server den Adapter. Für systemeigene Adapter geschieht dies unmittelbar. Für verwaltete Adapter ist diese Vorgehensweise wegen des Garbage Collection-Prozesses von .NET weniger obligatorisch. Der Adapter sollte in Beenden blockieren und alle erforderlichen Bereinigungsarbeiten ausführen, bis er zur Zerstörung bereit ist.

Beenden isolierter Empfangsadapter

Isolierte Empfangsadapter verfügen nicht über "Beenden ", da sie nicht im BizTalk-Dienst gehostet werden. Stattdessen sollten sie IBTTransportProxy aufrufen. TerminateIsolatedReceiver , um die Messaging-Engine darüber zu informieren, dass sie gerade heruntergefahren wird.

Bereinigen von COM-Objekten mit 'Marshal.ReleaseComObject'

Beim Schreiben von verwaltetem Code, in dem COM-Objekte verwendet werden, erstellt die Common Language Runtime (CLR) Proxyobjekte, die Verweise zu den COM-Objekten enthalten. Bei den Proxyobjekten handelt es sich um verwaltete Objekte, die den gängigen Regeln der Garbage Collection unterliegen. Es besteht insofern ein Problem, dass der Garbage Collector lediglich den von den .NET-Laufzeitmodulen reservierten Speicher erkennt und auf das COM-Objekt keinen Zugriff hat. Proxyobjekte sind klein, daher kann ein großes COM-Objekt u. U. im Speicher verbleiben, da es vom CLR-Garbage Collector nicht erkannt wird.

Um dieses Problem zu vermeiden, geben Sie die zugrunde liegenden COM-Objekte explizit frei, wenn Sie damit fertig sind, insbesondere alle IBTTransportBatch-Objekte . Dazu rufen Sie Marshal auf. ReleaseComObject.

Hinweis

ReleaseComObject gibt die Anzahl der verbleibenden Verweise zurück und gibt das COM-Objekt nur frei, wenn dieser zurückgegebene Wert 0 ist. Häufig wird ReleaseComObject in einer Schleife aufgerufen, um sicherzustellen, dass das Objekt freigegeben wird. Nachdem dies abgeschlossen ist, sollten Sie SuppressFinalize für dieses Objekt aufrufen, da es nichts zu finalisieren gibt. In einem letzten Schritt muss überprüft werden, ob es sich tatsächlich um ein COM-Objekt handelt.

Im folgenden Code ist der oben beschriebene Vorgang dargestellt:

if (Marshal.IsComObject (batch))  
(  
While (0 <Marshal.ReleaseComObject(batch)  
;  
GC.SuppressFinalize (batch);  
  

Die explizite Freigabe des IBTTransportBatch-Objekts , das von GetBatch zurückgegeben wird, kann zu einer erheblichen Leistungsverbesserung führen.

Schließen Sie einen Adapter stets mit 'Terminate'

Damit BizTalk Server Ihren Code als Adapter erkennen kann, müssen Sie eine Schnittstelle namens IBTTransportControl implementieren. Mit dieser Schnittstelle wird festgelegt, wie BizTalk Server mit Ihrem Adapter kommuniziert. Sie wird folgendermaßen definiert:

public interface IBTTransportControl   
{  
void Initialize(IBTTransportProxy transportProxy);  
void Terminate();  
}  

Die Schnittstelle enthält zwei Methoden: Initialize und Terminate.

Initialisieren

BizTalk Server ruft die Initialize-Methode auf, nachdem die Adapterassembly geladen wurde. Dadurch wird der Transportproxy (Haupthandle für BizTalk Server) an den Adapter übergeben. Die Implementierung von Initialize speichert einfach den Transportproxy in einer Membervariablen.

Terminate

BizTalk Server ruft die Terminate-Methode beim Herunterfahren des Diensts auf, um dem Adapter Zeit zu geben, die Ausführung aller Batches abzuschließen. Dies macht die Implementierung der Terminate-Methode viel wichtiger.

Der Adapter sollte von einem Beenden-Aufruf erst zurückgegeben werden, wenn alle ausstehenden Arbeiten abgeschlossen sind. Wenn BizTalk Server Beenden aufruft, sollte der Adapter versuchen, alle aktuellen Aufgaben zu beenden und keine neuen zu starten.

Da Beenden im Rahmen des Herunterfahrens des Diensts aufgerufen wird, beendet der Dienststeuerungs-Manager den Prozess, wenn der Adapter dauerhaft in Beenden blockiert. In diesem Fall wird vom Dienstkontroll-Manager beim Beenden des BizTalk Server-Diensts eine Warnung angezeigt. Vermeiden Sie nach Möglichkeit ein solches vorzeitiges Beenden des Adapters. Wenn der Beendigungsvorgang vom Adapter nicht ordnungsgemäß ausgeführt wird und noch immer Threads aktiv sind, wenn der Prozess beendet wird, tritt in BizTalk Server eventuell eine Zugriffsverletzung auf.

Aufgrund des asynchronen Charakters der Schnittstelle für BizTalk Server ist es wahrscheinlich, dass unter Last viele Batches vorhanden sind und daher immer noch Threads ausgeführt werden. Der Beenden-Aufruf sollte implementiert werden, um auf den Abschluss jedes Batches zu warten, den der Adapter erfolgreich auf BizTalk Server ausgeführt hat, bevor sie fortfahren. Die Schlussfolgerung des Batches wird durch den BatchComplete-Rückruf von BizTalk Server signalisiert. Der Beenden-Aufruf sollte bei jedem ausstehenden BatchComplete warten, um zu geschehen. Die Ausführung des Batches muss jedoch erfolgreich sein. Das heißt, der Aufruf von IBTTransportBatch::Done darf nicht fehlschlagen. Wenn der Aufruf von IBTTransportBatch::Done fehlschlägt, gibt es keinen Batchrückruf.

Auch wenn Sie feststellen, dass Ihrem Adapter Synchronisierungscode hinzugefügt werden muss, bleibt die Implementierung überschaubar.

Ein einfacher Ansatz besteht darin, ein zusammengesetztes Synchronisierungsobjekt mit Enter- und Leave-Methoden für die Workerthreads und eine Beendigungsmethode zu implementieren, die blockiert, während sich ein Thread noch innerhalb der geschützten Ausführung befindet. (Die Lösung ähnelt übrigens sehr der vertrauten Struktur mit mehreren Readern und einem einzelnen Writer, in der die Workerthreads als Leser und die Terminate-Methode als Writer betrachtet werden können.)

Die Beendigungsmethode lautet wie folgt:

void terminate ()  
{  
this.control.Terminate();  
}  

Für jeden Arbeitsthread:

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();  
}  

Im Rückruf von BizTalk Server:

batchComplete (…)  
{  
//  the callback from BizTalk Server  
//  process results  
this.control.Leave();  
}  

BizTalk Server wird im Basisadapterbeispiel mit dem Beispielcode ControlledTermination.cs ausgeliefert, der den hier beschriebenen Synchronisierungsmechanismus zeigt.