2009-08-15 5 views
6

Récemment, j'ai rencontré cette situation où je voulais afficher un formulaire sur un autre thread (pas le thread principal/UI). J'ai utilisé un thread threadpool. Le formulaire hébergeait un RCW (pour un composant COM). Instancier le formulaire m'a donné une exception que le fil doit être un STA. J'ai essayé de définir l'état de l'appartement comme STA. Mais, cela n'a pas fonctionné non plus. J'ai finalement fini par créer un thread explicitement et cela a fonctionné (j'ai utilisé ShowDialog et n'ai pas besoin de créer une pompe à meesage).Pourquoi ne pouvons-nous pas changer l'état de l'appartement d'un thread ThreadPool et pourquoi n'avons-nous pas besoin d'un messagepump quand ShowDialog est utilisé?

EDIT:

  • Je sais que threadpool threads sont MTA. Mais, pourquoi ne peut-il pas être réglé sur STA? Juste curieux à ce sujet.
  • Une autre question qui vient à sauté ma tête: Pourquoi ne pas besoin d'une pompe de message
    lorsque showDialog() (à
    afficher un formulaire) est utilisé

Répondre

8

L'appartement est sélectionné par un appel à CoInitializeEx(). Un thread dans le pool de threads a déjà fait cet appel, en changeant l'appartement après que cet appel ne soit pas possible. Qu'un pool de threads choisirait MTA a du sens, il est en fin de compte conçu comme un thread de travail et ne devrait pas être bloqué par des appels de méthodes qui doivent être marshalés. La sélection d'un appartement à un seul thread a l'exigence supplémentaire de pomper une boucle de message. Quelque chose que vous n'attendriez jamais d'un thread threadpool. La boucle de message est nécessaire car c'est le véhicule que COM utilise pour rassembler un appel effectué sur un autre thread. Cet appel doit être "injecté" dans le thread STA, ce qui n'est possible que si le thread est dans un état de repos connu. Si ce n'est pas le cas, un tel appel entraînerait des problèmes majeurs de ré-entrée. Ce qu'il fait parfois même si le fil est en train de pomper la boucle.

Vous n'aviez pas besoin de pomper vous-même une boucle de message avec Application.Run() car ShowDialog() lance sa propre boucle de messages. Voilà comment cela gagne la modalité. Cette boucle imbriquée se ferme dès que la boîte de dialogue se ferme.

+0

Merci pour la réponse. Pouvez-vous pointer vers un lien, qui dit que ShowDialog() commence sa propre boucle de message. –

+0

http://www.red-gate.com/products/reflector. Conseillé. –

+0

Merci. Application.RunDialog (this) fait l'affaire. –

8

Vous ne devriez pas compter sur comportement spécifique pour les threads de pool de threads. En général, un thread dans le pool de threads doit pouvoir être remplacé à tout moment par le CLR, à votre insu. Les threads de pool de threads sont destinés à être utilisés avec des tâches simples, de préférence de courte durée.

Si vous voulez avoir un contrôle fin sur les paramètres de fil, vous devez créer un fil dédié. Définir l'état de l'appartement est un parfait exemple de cela.


En plus de ce qui précède, des raisons théoriques, il y a un problème pratique avec ce que vous essayez. L'hébergement d'un formulaire sur un deuxième thread ne fonctionne pas (sans beaucoup de travail supplémentaire en place). Les formulaires doivent être exécutés sur le même thread que la pompe de message. Dans le cas contraire, ils ne recevront aucun message Windows et ne seront pas mis à jour correctement. Vous pouvez créer un formulaire sur un thread séparé si vous implémentez une pompe de messages complète pour ce thread, mais il est généralement préférable de simplement placer vos éléments de travail sur les threads d'arrière-plan et d'utiliser des techniques de programmation asynchrones pour conserver votre interface utilisateur. thread sensible.

+0

Merci pour la réponse. "Un thread dans le pool de threads devrait pouvoir être remplacé à tout moment par le CLR, à votre insu." Je ne le savais pas. Qu'est-ce que cela signifie exactement? –

+1

Le pool de threads crée et détruit des threads pendant l'exécution de votre programme. Il n'y a pas (nécessairement) juste un nombre fixe de threads dans le pool de threads. Le pool de threads de .NET 4 est encore plus flexible à cet égard. Il a toutes sortes de nouveaux outils pour le vol de travail, etc., qui le font engendrer et détruire des threads pendant l'exécution de votre application. –

+0

oh..yes Je suis totalement conscient de la pompe de message. Ainsi, créer un formulaire via un thread de pool de threads ou un nouveau thread nécessitera l'ajout d'une pompe de message à ce thread. Mais, j'utilise ShowDialog() pour afficher le formulaire et cela ne nécessite pas de pompe de message car c'est un appel bloquant. En fait, j'étais juste curieux de savoir pourquoi nous ne pouvons pas changer l'état d'appartement d'un thread ThreadPool pour être STA. Merci. –

Questions connexes