STAThread et multithreading

102

Extrait de l'article MSDN sur STAThread:

Indique que le modèle de thread COM pour une application est STA (single-threaded apartment).

(Pour référence, c'est l'article entier .)

Appartement à un seul thread ... OK, ça m'a dépassé la tête. De plus, j'ai lu quelque part qu'à moins que votre application n'utilise l'interopérabilité COM, cet attribut ne fait rien du tout. Alors, que fait-il exactement et comment affecte-t-il les applications multithread? Les applications multithreads (qui incluent tout ce qui va de toute personne utilisant Timers aux appels de méthodes asynchrones, pas seulement des threadpools et autres) devraient utiliser MTAThread, même si c'est «juste pour être sûr»? Que font réellement STAThread et MTAThread?

Matthew Scharley
la source

Réponses:

60

Le threading d'appartement est un concept COM; si vous n'utilisez pas COM et qu'aucune des API que vous appelez n'utilise COM «sous les couvertures», vous n'avez pas à vous soucier des appartements.

Si vous devez connaître les appartements, les détails peuvent devenir un peu compliqués ; une version probablement trop simplifiée est que les objets COM marqués comme STA doivent être exécutés sur un STAThread et les objets COM marqués MTA doivent être exécutés sur un thread MTA. En utilisant ces règles, COM peut optimiser les appels entre ces différents objets, évitant le marshaling là où ce n'est pas nécessaire.

Bruce
la source
7
C'est trop simplifié. Les objets multithreads peuvent s'exécuter dans n'importe quel thread. Les objets threadés d'appartement ne peuvent s'exécuter que dans l'appartement dans lequel ils ont été créés.
1800 INFORMATION
28
Un appel d'un objet STA sur un thread STA, à un objet MTA, sera marshalé vers un thread MTA (à moins que l'objet MTA implémente le marshaleur à thread libre). Comme je l'ai dit, les détails peuvent devenir compliqués. (J'ai travaillé dans l'équipe COM pendant plusieurs années avec un sourire )
Bruce
9
Parfois, vous devez en être conscient même si vous n'utilisez pas directement COM. Un thread doit utiliser le modèle Single-Threaded Apartment s'il affiche des fenêtres graphiques. C'est pourquoi [STAThread] est toujours affiché au-dessus de la méthode principale dans une application Windows Forms.
Justin Ethier
6
Quelque chose comme une boîte de dialogue Police ou Fichier ne pourrait pas utiliser COM sans que vous le sachiez? Je suppose qu'ils le font en interne, cela ne signifierait-il pas que presque toutes les applications Windows Forms nécessiteraient la définition de STAThread? Pardonnez mon hypothèse naieve car je n'ai pas réellement fait de programmation COM.
Brett Ryan
4
Une réponse plus détaillée pour ceux qui sont intéressés: stackoverflow.com/questions/4154429/apartmentstate-for-dummies
jgauffin
3

Ce que cela fait, il s'assure que CoInitializec'est appelé en spécifiant COINIT_APARTMENTTHREADED comme paramètre. Si vous n'utilisez aucun composant COM ou contrôle ActiveX, cela n'aura aucun effet sur vous. Si vous le faites, c'est un peu crucial.

Les contrôles qui sont threadés cloisonnés sont en fait un thread unique, les appels qui leur sont effectués ne peuvent être traités que dans le cloisonnement dans lequel ils ont été créés.

Quelques détails supplémentaires de MSDN:

Les objets créés dans un cloisonnement à un seul thread (STA) reçoivent des appels de méthode uniquement à partir du thread de leur cloison, de sorte que les appels sont sérialisés et arrivent uniquement aux limites de la file d'attente de messages (lorsque la fonction Win32 PeekMessage ou SendMessage est appelée).

Les objets créés sur un thread COM dans un cloisonnement multithread (MTA) doivent pouvoir recevoir à tout moment des appels de méthode d'autres threads. Vous implémentez généralement une forme de contrôle d'accès concurrentiel dans le code d'un objet multithread à l'aide de primitives de synchronisation Win32 telles que des sections critiques, des sémaphores ou des mutex pour aider à protéger les données de l'objet.

Lorsqu'un objet configuré pour s'exécuter dans la cloison filetée neutre (NTA) est appelé par un thread qui se trouve dans un STA ou le MTA, ce thread est transféré vers le NTA. Si ce thread appelle par la suite CoInitializeEx, l'appel échoue et renvoie RPC_E_CHANGED_MODE.

1800 INFORMATIONS
la source
L'article MSDN est utile d'un point de vue COM, mais pouvez-vous me dire quand .NET appelle CoInitialize()en réponse à l' STAThreadattribut / ApartmentState? Remarque: l'article sur MSDN est ici: fonction CoInitializeEx .
jrh
Est - thread - > SetApartment utiliser en CoInitialize()interne? J'ai tracé l'attribut STAThread tout en bas mais la piste est devenue froide (je ne trouve pas la source pour Thread::SetApartment). La classe Thread de thread.h (le thread.h COM) est-elle documentée n'importe où? Est-ce MFC, ATL ou autre chose?
jrh
@jrh Je ne connais pas plus de détails que cela désolé
1800 INFORMATION
-15

STAThread est écrit avant la fonction Main d'un projet C # GUI. Il ne fait rien mais permet au programme de créer un seul thread.

Zeinth
la source