Dans ce fil (publié il y a environ un an), il y a une discussion sur les problèmes qui peuvent survenir lors de l'exécution de Word dans une session non interactive. Le conseil (assez fort) qui y est donné est de ne pas le faire. Dans un article, il est indiqué «Les API Office supposent toutes que vous exécutez Office dans une session interactive sur un bureau, avec un moniteur, un clavier et une souris et, surtout, une pompe à messages». Je ne sais pas ce que c'est. (Je programme en C # depuis environ un an seulement; mon autre expérience de programmation a été principalement avec ColdFusion.)
Mettre à jour:
Mon programme parcourt un grand nombre de fichiers RTF pour extraire deux informations utilisées pour construire un numéro de rapport médical. Plutôt que d'essayer de comprendre comment fonctionnent les instructions de formatage dans RTF, j'ai décidé de simplement les ouvrir dans Word et d'extraire le texte de là (sans réellement démarrer l'interface graphique). Parfois, le programme a eu un hoquet au milieu du traitement d'un fichier et a laissé un fil Word ouvert attaché à ce document (je dois encore trouver comment fermer celui-ci). Lorsque j'ai relancé le programme, bien sûr, j'ai reçu une notification indiquant qu'un fil de discussion utilisait ce fichier et est-ce que je voulais ouvrir une copie en lecture seule? Quand j'ai dit Oui, l'interface graphique de Word est soudainement sortie de nulle part et a commencé à traiter les fichiers. Je me demandais pourquoi cela arrivait;
la source
Réponses:
Une boucle de message est un petit morceau de code qui existe dans n'importe quel programme Windows natif. Cela ressemble à peu près à ceci:
L'API Win32 GetMessage () récupère un message de Windows. Votre programme y passe généralement 99,9% de son temps à attendre que Windows lui dise que quelque chose d'intéressant s'est produit. TranslateMessage () est une fonction d'assistance qui traduit les messages du clavier. DispatchMessage () garantit que la procédure de fenêtre est appelée avec le message.
Chaque programme .NET activé par l'interface graphique a une boucle de message, il est démarré par Application.Run ().
La pertinence d'une boucle de message pour Office est liée à COM. Les programmes Office sont des programmes compatibles COM, c'est ainsi que fonctionnent les classes Microsoft.Office.Interop. COM s'occupe du threading pour le compte d'une coclasse COM, il garantit que les appels effectués sur une interface COM sont toujours effectués à partir du thread correct. La plupart des classes COM ont une clé de registre dans le registre qui déclare leur ThreadingModel, de loin les plus courants (y compris Office) utilisent "Appartement". Ce qui signifie que le seul moyen sûr d'appeler une méthode d'interface est de faire l'appel depuis le même thread qui a créé l'objet de classe. Ou pour le dire autrement: de loin, la plupart des classes COM ne sont pas thread-safe.
Chaque thread compatible COM appartient à un cloisonnement COM. Il existe deux types, les appartements à un seul filetage (STA) et un appartement à plusieurs threads (MTA). Une classe COM à thread cloisonné doit être créée sur un thread STA. Vous pouvez le voir dans les programmes .NET, le point d'entrée du thread d'interface utilisateur d'un programme Windows Forms ou WPF a l'attribut [STAThread]. Le modèle d'appartement pour les autres threads est défini par la méthode Thread.SetApartmentState ().
De grandes parties de la plomberie Windows ne fonctionneront pas correctement si le filetage de l'interface utilisateur n'est pas STA. Notamment Drag + Drop, le presse-papiers, les boîtes de dialogue Windows comme OpenFileDialog, des contrôles comme WebBrowser, des applications UI Automation comme des lecteurs d'écran. Et de nombreux serveurs COM, comme Office.
Une exigence absolue pour un thread STA est qu'il ne doit jamais se bloquer et doit pomper une boucle de message. La boucle de message est importante car c'est ce que COM utilise pour marshaler un appel de méthode d'interface d'un thread à un autre. Bien que .NET facilite le marshaling des appels (Control.BeginInvoke ou Dispatcher.BeginInvoke par exemple), c'est en fait une chose très délicate à faire. Le thread qui exécute l'appel doit être dans un état connu. Vous ne pouvez pas simplement interrompre arbitrairement un thread et le forcer à faire un appel de méthode, ce qui causerait d'horribles problèmes de rentrée. Un thread doit être "inactif", pas occupé à exécuter un code qui modifie l'état du programme.
Vous pouvez peut-être voir où cela mène: oui, lorsqu'un programme exécute la boucle de message, il est inactif. Le marshaling réel a lieu via une fenêtre masquée créée par COM, il utilise PostMessage pour que la procédure de fenêtre de cette fenêtre exécute le code. Sur le fil STA. La boucle de message garantit que ce code s'exécute.
la source
La "pompe à messages" est une partie centrale de tout programme Windows qui est responsable de l'envoi de messages de fenêtrage aux différentes parties de l'application. C'est le cœur de la programmation de l'interface utilisateur Win32. En raison de son omniprésence, de nombreuses applications utilisent la pompe de messages pour transmettre des messages entre différents modules, c'est pourquoi les applications Office seront interrompues si elles sont exécutées sans interface utilisateur.
Wikipedia a une description de base .
la source
John parle de la façon dont le système Windows (et d'autres systèmes basés sur des fenêtres - X Window , Mac OS d'origine ...) implémentent des interfaces utilisateur asynchrones en utilisant des événements via un système de messagerie.
Dans les coulisses de chaque application, il y a un système de messagerie où chaque fenêtre peut envoyer des événements à d'autres fenêtres ou écouteurs d'événements - ceci est mis en œuvre en ajoutant un message à la file d'attente de messages. Il existe une boucle principale qui s'exécute toujours en regardant cette file d'attente de messages, puis en distribuant les messages (ou événements) aux écouteurs.
L'article de Wikipedia Boucle de message dans Microsoft Windows montre un exemple de code d'un programme Windows de base - et comme vous pouvez le voir au niveau le plus élémentaire, un programme Windows n'est que la «pompe à messages».
Donc, pour tout rassembler. La raison pour laquelle un programme Windows conçu pour prendre en charge une interface utilisateur ne peut pas agir en tant que service est qu'il a besoin que la boucle de messages s'exécute en permanence pour activer la prise en charge de l'interface utilisateur. Si vous l'implémentez en tant que service comme décrit, il ne pourra pas traiter la gestion des événements asynchrones internes.
la source
Dans COM , une pompe de messages sérialise et désérialise les messages envoyés entre les appartements. Un cloisonnement est un mini processus dans lequel les composants COM peuvent être exécutés. Les appartements sont disponibles en mode fileté unique et fileté gratuit. Les appartements à un seul thread sont principalement un système hérité pour les applications de composants COM qui ne prennent pas en charge le multi-threading. Ils étaient généralement utilisés avec Visual BASIC (car cela ne prenait pas en charge le code multi-thread) et les applications héritées.
Je suppose que l'exigence de la pompe de message pour Word provient de l'API COM ou de parties de l'application qui ne sont pas thread-safe. Gardez à l'esprit que les modèles de thread .NET et de garbage collection ne fonctionnent pas correctement avec COM prêt à l'emploi. COM a un mécanisme de garbage collection et un modèle de thread très simplistes qui vous obligent à faire les choses à la manière COM. L'utilisation des assemblys PIA Office standard vous oblige toujours à arrêter explicitement les références d'objet COM, vous devez donc garder une trace de chaque handle COM créé. Les PIA créeront également des éléments dans les coulisses si vous ne faites pas attention.
L'intégration .NET-COM est un sujet à part entière, et il existe même des livres écrits sur le sujet. Même l'utilisation des API COM pour Office à partir d'une application de bureau interactive vous oblige à franchir des obstacles et à vous assurer que les références sont explicitement publiées.
Office peut être considéré comme non sécurisé pour les threads, vous aurez donc besoin d'une instance distincte de Word, Excel ou d'autres applications Office pour chaque thread. Vous devrez engager la surcharge de démarrage ou maintenir un pool de threads. Un pool de threads devrait être méticuleusement testé pour s'assurer que toutes les références COM ont été correctement libérées. Même le démarrage et l'arrêt des instances vous obligent à vous assurer que toutes les références sont libérées correctement. Le fait de ne pas mettre en point vos i et croiser vos t ici entraînera la fuite d'un grand nombre d'objets COM morts et même d'instances entières de Word en cours d'exécution.
la source
Wikipedia suggère que cela signifie la boucle d'événements principale du programme .
la source
Je pense que cette discussion sur Channel 9 a une belle explication succincte:
la source