Share via


Procédure d’arrêt d’un adaptateur

Les rubriques suivantes fournissent des instructions sur la façon appropriée d'arrêter un adaptateur.

Arrêt d'un adaptateur

Lorsque le moteur de messagerie s’arrête, il appelle IBTTransportControl. Terminez sur chaque adaptateur in-process. Après le retour de la méthode, BizTalk Server détruit l'adaptateur. Pour les adaptateurs natifs, cette destruction se produit immédiatement, tandis que pour les adaptateurs gérés, le moment précis de cette destruction est moins déterministe, en raison du processus de nettoyage de la mémoire .NET. L’adaptateur doit se bloquer dans Terminer et effectuer tout le travail de nettoyage nécessaire jusqu’à ce qu’il soit prêt à être détruit.

Arrêt d'adaptateurs de réception isolés

Les adaptateurs de réception isolés ne sont pas appelés sur eux, car ils ne sont pas hébergés dans le service BizTalk. Au lieu de cela, ils doivent appeler IBTTransportProxy. TerminateIsolatedReceiver pour informer le moteur de messagerie qu’il est sur le point de s’arrêter.

Nettoyage d'objets COM à l'aide de Marshal.ReleaseComObject

Lors de la rédaction de code managé utilisant des objets COM, le CLR (Common Language Runtime) génère des objets proxy contenant les références aux objets COM. Les objets proxy sont des objets managés soumis aux règles habituelles du nettoyage de la mémoire. Le problème vient du fait que le garbage collector accède uniquement à la mémoire allouée par les modes d'exécution .NET et qu'il ne tient pas compte de l'objet COM. Étant donné que les objets proxy sont petits, un grand objet COM peut être oublié dans la mémoire, car le garbage collector CLR ne l'a pas pris en considération.

Pour éviter ce problème, libérez explicitement les objets COM sous-jacents lorsque vous en avez terminé, en particulier les objets IBTTransportBatch . Pour ce faire, appelez Marshal. ReleaseComObject.

Notes

ReleaseComObject retourne le nombre de références restantes et libère l’objet COM uniquement lorsque cette valeur retournée est égale à zéro. Souvent , ReleaseComObject est appelé dans une boucle pour s’assurer que l’objet est libéré. Une fois cette opération terminée, vous devez appeler SuppressFinalize sur cet objet, car il n’y a rien à finaliser. La dernière étape consiste à vérifier l'existence de l'objet COM.

Le code suivant présente le processus décrit ci-dessus :

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

La libération explicite de l’objet IBTTransportBatch retourné par GetBatch peut améliorer considérablement les performances.

Utilisation systématique de Terminate lors de l'arrêt d'un adaptateur

Pour BizTalk Server de reconnaître votre code en tant qu’adaptateur, vous devez implémenter une interface appelée IBTTransportControl. Cette interface détermine la façon dont BizTalk Server communique avec votre adaptateur. Elle est définie de la façon suivante :

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

L’interface contient deux méthodes, Initialize et Terminate.

Initialiser

BizTalk Server appelle la méthode Initialize après avoir chargé l’assembly de l’adaptateur. Il procède ainsi pour transmettre le proxy de transport (le handle principal vers BizTalk Server) à l'adaptateur. L’implémentation d’Initialize stocke simplement le proxy de transport dans une variable membre.

Terminate

BizTalk Server appelle la méthode Terminate lors de l’arrêt du service pour donner à l’adaptateur le temps de terminer l’exécution de tous les lots. Cela rend l’implémentation de la méthode Terminate beaucoup plus impliquée.

L’adaptateur ne doit pas revenir d’un appel Terminate tant que le travail en attente n’est pas terminé. Lorsque BizTalk Server appelle Terminate, l’adaptateur doit essayer d’arrêter toutes ses tâches actuelles et de ne pas en démarrer de nouvelles.

Étant donné que Terminate est appelé dans le cadre de l’arrêt du service, le gestionnaire de contrôle de service met fin au processus si l’adaptateur se bloque perpétuellement dans Terminate. Dans ce cas, vous recevez un avertissement du gestionnaire de contrôle de service lorsqu'il arrête le service BizTalk Server. Si possible, évitez d'arrêter l'adaptateur prématurément. Si l'adaptateur ne traite pas le processus d'arrêt de façon appropriée et que des threads sont toujours en cours d'exécution au début du processus d'arrêt, il se peut que vous receviez un message de violation d'accès de la part de BizTalk Server au moment de l'arrêt.

En raison de la nature asynchrone de l'interface vers BizTalk Server, il est probable que, en condition de charge, de nombreux lots, et donc de nombreux threads, soient encore en cours d'exécution. L’appel Terminate doit être implémenté pour attendre la fin de chaque lot que l’adaptateur a exécuté avec succès sur BizTalk Server avant de continuer. La conclusion du lot est signalée par le rappel BatchComplete de BizTalk Server. L’appel Terminate doit attendre chaque BatchComplete en attente pour se produire. En outre, l'exécution des lots doit être réussie. Autrement dit, l’appel à IBTTransportBatch ::Done ne doit pas échouer. Si l’appel à IBTTransportBatch ::Done échoue, il n’y a pas de rappel par lot.

Ensuite, vous devez ajouter du code de synchronisation à votre adaptateur, procédure relativement simple.

Une approche simple consiste à implémenter un objet de synchronisation composé avec des méthodes d’entrée et de sortie pour les threads de travail et une méthode terminate qui bloque un thread pendant qu’un thread se trouve toujours dans l’exécution protégée. (Incidemment, la solution est très similaire à la structure familière à plusieurs lecteurs, à écriture unique, où les threads de travail peuvent être considérés comme des lecteurs et la méthode terminate comme l’enregistreur.)

La méthode terminate est la suivante :

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

Pour chaque thread de travail :

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

Dans le rappel émis par BizTalk Server :

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

BizTalk Server est fourni avec l’exemple de code ControlledTermination.cs dans l’exemple d’adaptateur de base, montrant le mécanisme de synchronisation décrit ici.