Réponses:
Le modèle de thread COM est appelé modèle "cloisonné", dans lequel le contexte d'exécution des objets COM initialisés est associé à un seul thread (Single Thread Apartment) ou à plusieurs threads (Multi Thread Apartment). Dans ce modèle, un objet COM, une fois initialisé dans un appartement, fait partie de cet appartement pendant la durée de son exécution.
Le modèle STA est utilisé pour les objets COM qui ne sont pas thread-safe. Cela signifie qu'ils ne gèrent pas leur propre synchronisation. Une utilisation courante de ceci est un composant d'interface utilisateur. Donc, si un autre thread doit interagir avec l'objet (par exemple, en appuyant sur un bouton dans un formulaire), le message est organisé sur le thread STA. Le système de pompage de messages Windows Forms en est un exemple.
Si l'objet COM peut gérer sa propre synchronisation, le modèle MTA peut être utilisé lorsque plusieurs threads sont autorisés à interagir avec l'objet sans appels organisés.
Tout dépend de la façon dont les appels aux objets sont traités et de la protection dont ils ont besoin. Les objets COM peuvent demander au runtime de les protéger contre tout appel simultané de plusieurs threads; ceux qui ne peuvent pas être appelés simultanément à partir de différents threads, ils doivent donc protéger leurs propres données.
En outre, il est également nécessaire pour l'exécution d'empêcher un appel d'objet COM de bloquer l'interface utilisateur, si un appel est effectué à partir d'un thread d'interface utilisateur.
Un appartement est un endroit où vivre des objets, et ils contiennent un ou plusieurs fils. L'appartement définit ce qui se passe lors des appels. Les appels aux objets dans un appartement seront reçus et traités sur n'importe quel thread de cet appartement, à l'exception qu'un appel par un thread déjà dans le bon appartement est traité par lui-même (c'est-à-dire un appel direct à l'objet).
Les threads peuvent être soit dans un appartement à un seul thread (auquel cas ils sont le seul thread dans cet appartement) ou dans un appartement à plusieurs threads. Ils spécifient lequel lorsque le thread initialise COM pour ce thread.
Le STA est principalement destiné à la compatibilité avec l'interface utilisateur, qui est liée à un thread spécifique. Une STA reçoit des notifications d'appels à traiter en recevant un message de fenêtre vers une fenêtre cachée; lorsqu'il effectue un appel sortant, il démarre une boucle de message modale pour empêcher le traitement d'autres messages de fenêtre. Vous pouvez spécifier un filtre de message à appeler, afin que votre application puisse répondre à d'autres messages.
En revanche, tous les threads MTA partagent un seul MTA pour le processus. COM peut démarrer un nouveau thread de travail pour gérer un appel entrant si aucun thread n'est disponible, jusqu'à une limite de pool. Les threads effectuant des appels sortants se bloquent simplement.
Pour simplifier, nous ne considérerons que les objets implémentés dans les DLL, qui annoncent dans le registre ce qu'ils prennent en charge, en définissant la ThreadingModel
valeur de la clé de leur classe. Il y a quatre options:
ThreadingModel
valeur non présente). L'objet est créé sur le thread d'interface utilisateur principal de l'hôte et tous les appels sont dirigés vers ce thread. L'usine de classe ne sera appelée que sur ce thread.Apartment
. Cela indique que la classe peut s'exécuter sur n'importe quel thread en mode thread unique. Si le thread qui le crée est un thread STA, l'objet s'exécutera sur ce thread, sinon il sera créé dans le STA principal - si aucun STA principal n'existe, un thread STA sera créé pour lui. (Cela signifie que les threads MTA qui créent des objets Apartment rassembleront tous les appels vers un thread différent.) La fabrique de classes peut être appelée simultanément par plusieurs threads STA, elle doit donc protéger ses données internes contre cela.Free
. Cela indique une classe conçue pour s'exécuter dans le MTA. Il sera toujours chargé dans le MTA, même s'il est créé par un thread STA, ce qui signifie à nouveau que les appels du thread STA seront organisés. En effet, un Free
objet est généralement écrit dans l'espoir qu'il peut bloquer.Both
. Ces classes sont flexibles et se chargent dans l'appartement à partir duquel elles sont créées. Cependant, ils doivent être écrits pour répondre aux deux ensembles d'exigences: ils doivent protéger leur état interne contre les appels simultanés, dans le cas où ils sont chargés dans le MTA, mais ne doivent pas bloquer, dans le cas où ils sont chargés dans un STA.À partir du .NET Framework, utilisez simplement [STAThread]
n'importe quel thread qui crée l'interface utilisateur. Les threads de travail doivent utiliser le MTA, sauf s'ils vont utiliser Apartment
des composants COM marqués, auquel cas utilisez le STA pour éviter de surcharger les problèmes de surcharge et d'évolutivité si le même composant est appelé à partir de plusieurs threads (car chaque thread devra attendre le composant à son tour). C'est beaucoup plus simple si vous utilisez un objet COM distinct par thread, que le composant soit dans le STA ou le MTA.
Je trouve les explications existantes trop englouties. Voici mon explication en anglais simple:
STA: si un thread crée un objet COM qui est défini sur STA (lorsque vous appelez CoCreateXXX, vous pouvez passer un indicateur qui définit l'objet COM en mode STA), seul ce thread peut accéder à cet objet COM (c'est ce que STA signifie - Appartement à un seul thread) ), tout autre thread essayant d'appeler des méthodes sur cet objet COM est sous le capot transformé silencieusement en remise de messages au thread qui crée (possède) l'objet COM. Cela ressemble beaucoup au fait que seul le thread qui a créé un contrôle d'interface utilisateur peut y accéder directement. Et ce mécanisme est destiné à empêcher les opérations de verrouillage / déverrouillage compliquées.
MTA: si un thread crée un objet COM qui est défini sur MTA, presque tous les threads peuvent appeler directement des méthodes dessus.
C'est à peu près l'essentiel. Bien qu'il y ait techniquement certains détails que je n'ai pas mentionnés, comme dans le paragraphe 'STA', le thread créateur doit lui-même être STA. Mais c'est à peu près tout ce que vous devez savoir pour comprendre STA / MTA / NA.
STA (Single Threaded Apartment) est fondamentalement le concept selon lequel un seul thread interagira avec votre code à la fois. Les appels dans votre appartement sont dirigés via des messages Windows (en utilisant une fenêtre non visible). Cela permet de mettre les appels en file d'attente et d'attendre la fin des opérations.
MTA (Multi Threaded Apartment) est l'endroit où de nombreux threads peuvent tous fonctionner en même temps et il vous incombe en tant que développeur de gérer la sécurité des threads.
Il y a beaucoup plus à apprendre sur les modèles de threading dans COM, mais si vous avez du mal à comprendre ce qu'ils sont, je dirais que comprendre ce qu'est le STA et comment il fonctionne serait le meilleur point de départ car la plupart des objets COM sont des STA.
Threads d'appartement, si un thread vit dans le même appartement que l'objet qu'il utilise, il s'agit d'un thread d'appartement. Je pense que ce n'est qu'un concept COM car ce n'est qu'une façon de parler des objets et des threads avec lesquels ils interagissent…
Chaque EXE qui héberge des contrôles COM ou OLE définit son état d'appartement. L'état de l'appartement est par défaut STA (et pour la plupart des programmes, il doit être STA).
STA - Tous les contrôles OLE par nécessité doivent vivre dans une STA. STA signifie que votre objet COM doit toujours être manipulé sur le thread d'interface utilisateur et ne peut pas être transmis à d'autres threads (un peu comme n'importe quel élément d'interface utilisateur dans MFC). Cependant, votre programme peut toujours avoir de nombreux threads.
MTA - Vous pouvez manipuler l'objet COM sur n'importe quel thread de votre programme.
Si je comprends bien, «l'appartement» est utilisé pour protéger les objets COM des problèmes de multithreading.
Si un objet COM n'est pas thread-safe, il doit le déclarer en tant qu'objet STA. Seul le thread qui l'a créé peut alors y accéder. Le thread de création doit se déclarer en tant que thread STA. Sous le capot, le thread stocke les informations STA dans son TLS (Thread Local Storage). Nous appelons ce comportement que le thread entre dans un appartement STA. Lorsque d'autres threads souhaitent accéder à cet objet COM, il doit organiser l'accès au thread de création. Fondamentalement, le thread de création utilise un mécanisme de messages pour traiter les appels entrants.
Si un objet COM est thread-safe, il doit le déclarer en tant qu'objet MTA. L'objet MTA est accessible par plusieurs threads.
Le code qui appelle les DLL d'objet COM (par exemple, pour lire des fichiers de données propriétaires), peut fonctionner correctement dans une interface utilisateur mais se bloquer mystérieusement à un service. La raison en est qu'à partir de .Net 2.0, les interfaces utilisateur supposent STA (thread-safe) tandis que les services supposent MTA ((avant cela, les services supposaient STA). La nécessité de créer un thread STA pour chaque appel COM dans un service peut ajouter une surcharge importante.