2009-09-15 6 views
4

J'ai une application C# qui utilise un composant COM. Ce composant COM nécessite une pompe de message (Application.Run()) pour effectuer son traitement. Cela signifie qu'il a été bloqué sur le fil principal. Mais j'ai récemment découvert qu'il est possible de démarrer une autre application. Exécutez sur un autre thread qui obtient son propre ApplicationContext. Donc je veux héberger le composant COM sur son propre thread à l'intérieur de son propre Application.Run(), mais je n'arrive pas à comprendre comment démarrer les choses sur le nouveau thread sans créer de formulaire d'interface utilisateur.Pompage de messages multithread sans seconde forme

Le WindowsFormsSynchronizationContext dont j'ai besoin pour communiquer avec le thread ne sera pas créé avant Application.Run(). Mais une fois que Application.Run() est appelée, je n'arrive pas à comprendre comment accéder au SynchronizationContext. Si je pouvais simplement déclencher un seul événement sur ce thread, je pourrais l'utiliser pour amorcer le tout (créer l'objet COM, etc.), mais il ne semble pas y avoir d'endroit où se connecter à la nouvelle boucle d'événement sans un formulaire . J'ai essayé toutes sortes de choses compliquées, comme l'installation d'un filtre de message (aucun message n'est levé sur le nouveau thread), la copie du contexte d'exécution dans un autre thread et la récupération du SynchronizationContext à partir de là (il refuse de copier ExecutionContext d'un thread déjà en cours d'exécution), récupérer Thread.CurrentContext avant de démarrer Application.Run(), puis en appelant DoCallbBack() (le DoCallback se termine sur le thread d'origine), etc Rien de ce que j'ai essayé fonctionne.

Répondre

6

Bryce,

Vous pourriez être en mesure d'adapter cet extrait de Anders Hejlsberg's talk about "The Future of C#". C'est une petite classe qui ajoute une pompe de message à un fil afin qu'il puisse ouvrir les fenêtres en utilisant une boucle de REPL, et ils auront une pompe de message attaché à eux.

Le code ressemble à ceci:

using System.Windows.Forms; 
using System.Threading; 
class UserInterfaceThread() 
{ 
    static Form window; 

    public UserInterfaceThread() 
    { 
     var thread = new Thread(() => { 
      window = new Form(); 
      var handle = window.Handle; 
      Application.Run(); 
      }); 
     thread.Start(); 
    } 
    public void Run(Action action) 
    { 
     window.Invoke(action); 
    } 
} 

La discussion relative à ce code se produit à 1 heure 5 minutes dans le discours de Anders, si vous voulez examiner.

+0

Il s'avère donc que créer un handle de fenêtre est ce qui instancie le SynchronizationContext et non le Application.Run(). Il suffit donc d'appeler "IntPtr handle = new Form(). Handle;" crée le WindowsFormsSynchronizationContext requis avant d'appeler Application.Run(). Merci beaucoup. –

Questions connexes