Condividi tramite


Come terminare un adapter

Gli argomenti seguenti forniscono istruzioni sulla corretta chiusura di un adapter.

Chiusura di un adapter

Quando il motore di messaggistica viene arrestato, chiama IBTTransportControl. Termina su ogni adattatore in-process. Al termine del metodo BizTalk Server elimina l'adapter. Per gli adapter nativi questa operazione viene eseguita immediatamente, mentre per gli adapter gestiti è più difficile stabilire il momento esatto a causa del processo di Garbage Collection di .NET. L'adattatore deve bloccarsi in Terminate ed eseguire tutte le operazioni di pulizia necessarie fino a quando non è pronto per essere eliminato definitivamente.

Chiusura di adapter di ricezione isolati

Gli adapter di ricezione isolati non dispongono di Chiamate Terminate perché non sono ospitate nel servizio BizTalk. Devono invece chiamare IBTTransportProxy. TerminateIsolatedReceiver per notificare al motore di messaggistica che stanno per essere arrestati.

Pulitura di oggetti COM mediante Marshal.ReleaseComObject

Quando si esegue la scrittura di codice gestito che utilizza oggetti COM, Common Language Runtime (CLR) genera oggetti proxy contenenti riferimenti agli oggetti COM. Gli oggetti proxy sono oggetti gestiti e sono soggetti alle tipiche regole di Garbage Collection. Il problema consiste nel fatto che il Garbage Collector è in grado di vedere soltanto la memoria allocata dai runtime di .NET e non riconosce l'oggetto COM. Dal momento che gli oggetti proxy sono di dimensioni ridotte, un oggetto COM di grandi dimensioni potrebbe rimanere in memoria perché non viene riconosciuto dal Garbage Collector di CLR.

Per evitare questo problema, rilasciare in modo esplicito gli oggetti COM sottostanti al termine dell'operazione, in particolare qualsiasi oggetto IBTTransportBatch . A tale scopo, chiamare Marshal. ReleaseComObject.

Nota

ReleaseComObject restituisce il numero di riferimenti rimanenti e rilascia solo l'oggetto COM quando questo valore restituito è zero. Spesso ReleaseComObject viene chiamato in un ciclo per assicurarsi che l'oggetto venga rilasciato. Al termine, devi chiamare SuppressFinalize su questo oggetto perché non c'è nulla da finalizzare. Verificare infine che l'oggetto sia effettivamente un oggetto COM.

Nel codice seguente viene illustrato il processo descritto sopra:

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

Il rilascio esplicito dell'oggetto IBTTransportBatch restituito da GetBatch può apportare un miglioramento significativo delle prestazioni.

Utilizzare sempre il metodo Terminate per chiudere un adapter

Per BizTalk Server riconoscere il codice come adattatore, è necessario implementare un'interfaccia denominata IBTTransportControl. Questa interfaccia definisce la modalità in cui BizTalk Server comunica con l'adapter ed è definita nel modo seguente:

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

L'interfaccia contiene due metodi, Initialize e Terminate.

Initialize

BizTalk Server chiama il metodo Initialize dopo il caricamento dell'assembly dell'adattatore. Questa chiamata viene eseguita per passare il proxy di trasporto (l'handle principale di BizTalk Server) all'adapter. L'implementazione di Initialize archivia semplicemente il proxy di trasporto in una variabile membro.

Terminate

BizTalk Server chiama il metodo Terminate all'arresto del servizio per assegnare all'adapter il tempo necessario per completare l'esecuzione di tutti i batch. In questo modo l'implementazione del metodo Terminate è molto più interessata.

L'adattatore non deve restituire da una chiamata Terminate fino al completamento di qualsiasi lavoro in sospeso. Quando BizTalk Server chiama Terminate, l'adapter deve tentare di arrestare tutte le attività correnti e non avviarne di nuove.

Poiché Terminate viene chiamato come parte dell'arresto del servizio, il gestore del controllo del servizio termina il processo se l'adattatore si blocca in modo perpetuo in Termina. In questo caso, all'interruzione del servizio BizTalk Server verrà visualizzato un messaggio di avviso di Gestione controllo servizi. Cercare in ogni caso di evitare di interrompere anticipatamente l'adapter in questo modo. Se l'adapter non è in grado di gestire il processo di chiusura in modo appropriato, e continua ad avere thread in esecuzione quando viene avviata la chiusura del processo, è possibile che venga restituito un errore di violazione di accesso da BizTalk Server al momento della chiusura.

A causa della natura asincrona dell'interfaccia di BizTalk Server, è probabile che sotto carico siano presenti numerosi batch e quindi thread ancora in esecuzione. La chiamata Terminate deve essere implementata per attendere la conclusione di ogni batch che l'adapter ha eseguito correttamente in BizTalk Server prima di procedere. La conclusione del batch viene segnalata dal callback batchComplete da BizTalk Server. La chiamata Terminate deve attendere ogni batchComplete in sospeso . L'esecuzione dei batch deve essere tuttavia completata correttamente. Ovvero, la chiamata a IBTTransportBatch::Done non deve avere esito negativo. Se la chiamata a IBTTransportBatch::Done ha esito negativo, non viene eseguito alcun callback batch.

Quando si arriva al punto di dover aggiungere codice di sincronizzazione all'adapter, l'implementazione è semplicissima.

Un approccio semplice consiste nell'implementare un oggetto di sincronizzazione composto con i metodi enter e leave per i thread di lavoro e un metodo terminate che blocca mentre un thread è ancora all'interno dell'esecuzione protetta. (Per inciso, la soluzione è molto simile alla familiare struttura a più lettori, a scrittura singola, in cui i thread di lavoro possono essere considerati come lettori e il metodo terminate come writer).

Il metodo terminate è il seguente:

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

Per ogni thread di lavoro:

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

Nella richiamata da BizTalk Server.

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

BizTalk Server fornito con codice di esempio ControlledTermination.cs nell'esempio dell'adapter di base, che mostra il meccanismo di sincronizzazione descritto qui.