136 votes

ApartmentState pour les nuls

Je viens de corriger un bug en utilisant ceci:

 _Thread.SetApartmentState(ApartmentState.STA);
 

Maintenant, j'aimerais comprendre ce que cela signifie et pourquoi cela fonctionne!

275voto

Hans Passant Points 475940

COM est le grand-père de .NET. Ils avaient assez nobles objectifs avec elle, l'une des choses qui COM ne mais .NET complètement saute est de fournir le filetage des garanties pour une classe. Une classe COM pouvez publier ce genre d'enfiler les exigences qu'il implique. Et la COM de l'infrastructure permet de s'assurer que ces exigences sont satisfaites.

C'est complètement absente .NET. Vous pouvez utiliser une File d'attente<> objet par exemple dans plusieurs threads, mais si vous n'avez pas verrouiller correctement, vous aurez un vilain bug dans votre code qui est très difficile à diagnostiquer.

Les détails exacts de COM threading sont trop volumineux pour tenir dans un post. Je vais me concentrer sur les spécificités de votre question. Un thread qui crée des objets COM a dire COM de quel genre de soutien qu'il veut donner à la COM des classes qui ont restreint les options de thread. La grande majorité de ces classes uniquement en charge soi-disant Appartement de filetage, de leurs méthodes d'interface ne peut en toute sécurité être appelée à partir de la même thread qui a créé l'instance. En d'autres termes, ils annoncent "je ne supporte pas de thread que ce soit, veuillez prendre soin de ne jamais m'appeler à partir de la fil mal". Même si le code client en fait ne l'appeler à partir d'un autre thread.

Il existe deux sortes, STA (Single Threaded Apartment) et le MTA. Il est précisé dans le CoInitializeEx() l'appel d'une fonction qui doit être appelée par n'importe quel thread qui fait n'importe quoi avec COM. Le CLR fait que l'appel automatiquement à chaque fois qu'il démarre un thread. Pour le démarrage principal fil conducteur de votre programme, il obtient la valeur de passer de l' [STAThread] ou [MTAThread] attribut sur votre méthode main (). Valeur par défaut est de MTA. Pour les threads que vous créez vous-même, il est déterminé par votre appel à SetApartmentState(). Valeur par défaut est de MTA. Pool de threads les threads sont toujours MTA, qui ne peut être changé.

Il y a beaucoup de code de Windows qui nécessite un STA. Des exemples notables sont le presse-papier, faites Glisser + Chute et la coquille boîtes de dialogue (comme OpenFileDialog). Le thread d'INTERFACE utilisateur de Windows Forms ou WPF projet doit toujours être PERSONNEL, comme le fait n'importe quel thread qui crée une fenêtre.

La promesse que vous faites à COM que votre thread STA cependant ne vous oblige à suivre le thread unique appartement de contrat. Ils sont assez raides et vous pouvez obtenir assez difficile à diagnostiquer des problèmes quand vous rompre le contrat. Les exigences sont que vous ne jamais bloquer le thread pour n'importe quel laps de temps et que la pompe une boucle de message. La seconde exigence est satisfaite par une WPF ou Winforms' thread de l'INTERFACE utilisateur, mais vous aurez besoin de prendre soin de vous-même si vous créez votre propre thread STA. La commune de diagnostic de la rupture du contrat est l'impasse.

Il est tout à fait un peu de soutien intégré dans le CLR à l'appui de ces exigences btw, vous aider à garder hors de l'ennui. Le verrouillage de l' instruction par exemple pompe un message en boucle quand il bloque sur un thread STA. Plus de la synchronisation des classes de faire ainsi, Mutex étant une exception notable. Ceci, cependant, ne s'occupe que de la jamais-bloc exigence, vous devez toujours créer votre propre boucle de message. Application.Run() dans WPF et Winforms.

J'ai déjà versé une réponse qui contient plus de détails à propos de l'importance d'avoir une boucle de message pour garder COM heureux. Vous trouverez les poster ici.

1voto

ArsenMkrt Points 24447

Ce post peut vous aider

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X