Dangers d’un thread MTA C # créant un object STA COM

Je suis actuellement en train de regarder un problème que nous rencontrons dans un service Windows .Net Framework 2.0 (C #) qui a un nombre X de threads MTA exécutant cet access aux composants COM. Chaque thread initialise sa propre instance de l’object composant com. L’object composant com ne contient aucun élément d’interface utilisateur. Il s’agit simplement d’une logique d’entreprise qui communique avec une firebase database de serveur SQL et une dll C # avec une interface COM qui effectue à son tour la communication par socket et l’access à la même firebase database de serveur SQL.

Grâce à mes recherches, j’ai constaté que vous ne devriez pas instancier des composants STA COM sur un thread MTA, mais je ne trouve pas de texte spécifique indiquant les dangers de ce phénomène. si bien.

Y aurait-il des problèmes de simultanéité avec le modèle décrit ci-dessus? Même si chaque thread MTA crée son propre object STA COM?

modifier

Le problème que nous rencontrons actuellement est une référence d’object non définie à l’instance d’une erreur d’object dans l’afficheur de la chaîne de connexion dans le bloc de code suivant. Cela se produit dans l’object COM C # appelé par l’object COM c ++:

IDbConnection connection; //Code omitted for brevity where connection is initialized connection.ConnectionSsortingng = myConnectionSsortingng; 

Type d’exception: System.NullReferenceException Message: La référence d’object n’est pas définie sur une instance d’un object. Données: System.Collections.ListDictionaryInternal TargetSite: Void ConnectionSsortingng_Set (System.Ssortingng) dans System.Data.OracleClient.OracleConnection.ConnectionSsortingng_Set (Valeur de chaîne) dans System.Data.OracleClient.OracleConnection.OracleConnection.set_ConnectionSsortingng (valeur de chaîne)

Il existe quatre “dangers” de base lorsque vous appelez à partir du MTA:

  • l’object COM est appartement threadé, très commun, et l’appel doit donc être marshalé à l’appartement qui possède l’object. La formulation techniquement correcte pour “STA COM”. Cela coûte cher , les appels marshalés aux petites méthodes sont généralement 10 000 fois plus lents.

  • l’object COM ne prend pas en charge un proxy pour organiser l’appel. C’est très facile à savoir, l’appel échouera avec E_NOINTERFACE.

  • le programmeur client ne se rend pas compte qu’il passe un appel du MTA et oublie de marshaler le pointeur d’interface. COM ne peut empêcher cela lors d’appels passés à un serveur COM en cours de traitement. Vous ne pouvez pas faire cette erreur dans un programme .NET, le CLR sera toujours marshal, mais facile à faire dans d’autres environnements d’exécution. Sinon, cela appelle la colère habituelle de faire des appels non fiables avec les threads, fonctionne lorsque vous déboguez le code, échoue de manière aléatoire en production et est impossible à déboguer.

  • l’auteur de COM a publié sa composante pour la rendre compatible avec MTA en déclarant son ThreadingModel comme Both ou Free. Mais il n’a pas testé suffisamment son code, écrire du code sans danger pour les threads est notoirement difficile. Particulièrement dangereux dans les classes .NET [ComVisible], car elles sont automatiquement enregistrées comme les deux et il est très facile d’oublier complètement de tester le code par rapport à cette promesse.

Votre extrait de code est bien trop impénétrable pour passer un appel, mais un candidat possible pour la 4ème puce. Autrement, aucun COM ne serait impliqué. Les fournisseurs de données tels qu’Oracle sont normalement libres de threads et soigneusement testés par des centaines de milliers de programmeurs.