Em esta discussão (publicado há um ano), há uma discussão dos problemas que podem vir com a executar o Word em uma sessão não-interativo. O conselho (bastante forte) dado ali é para não fazer isso. Em uma postagem é declarado "Todas as APIs do Office pressupõem que você está executando o Office em uma sessão interativa em um desktop, com um monitor, teclado e mouse e, o mais importante, uma bomba de mensagem." Não tenho certeza do que é. (Eu tenho programado em C # por apenas cerca de um ano; minha outra experiência de programação foi principalmente com ColdFusion.)
Atualizar:
Meu programa executa um grande número de arquivos RTF para extrair duas informações usadas para construir um número de relatório médico. Em vez de tentar descobrir como funcionam as instruções de formatação em RTF, decidi apenas abri-las no Word e retirar o texto de lá (sem realmente iniciar a GUI). Ocasionalmente, o programa travava no meio do processamento de um arquivo e deixava um encadeamento do Word aberto anexado a esse documento (ainda tenho que descobrir como encerrar aquele). Quando executei o programa novamente, é claro que recebi uma notificação de que havia um encadeamento usando aquele arquivo e eu queria abrir uma cópia somente leitura? Quando eu disse Sim, a GUI do Word apareceu de repente do nada e começou a processar os arquivos. Eu estava me perguntando por que isso aconteceu;
fonte
Respostas:
Um loop de mensagem é um pequeno trecho de código que existe em qualquer programa nativo do Windows. É mais ou menos assim:
A API Win32 GetMessage () recupera uma mensagem do Windows. Seu programa normalmente passa 99,9% do tempo lá, esperando que o Windows diga que algo interessante aconteceu. TranslateMessage () é uma função auxiliar que traduz mensagens do teclado. DispatchMessage () garante que o procedimento de janela seja chamado com a mensagem.
Cada programa .NET habilitado para GUI tem um loop de mensagem, ele é iniciado por Application.Run ().
A relevância de um loop de mensagem para o Office está relacionada ao COM. Os programas do Office são programas habilitados para COM, é assim que funcionam as classes Microsoft.Office.Interop. COM cuida do threading em nome de um coclass COM, ele garante que as chamadas feitas em uma interface COM sejam sempre feitas do thread correto. A maioria das classes COM tem uma chave de registro no registro que declara seu ThreadingModel, de longe as mais comuns (incluindo Office) usam "Apartment". O que significa que a única maneira segura de chamar um método de interface é fazendo a chamada do mesmo thread que criou o objeto de classe. Ou, colocando de outra forma: de longe, a maioria das classes COM não é segura para threads.
Cada segmento habilitado para COM pertence a um compartimento COM. Existem dois tipos, Single Threaded Apartments (STA) e um Multi Threaded Apartment (MTA). Uma classe COM threaded apartment deve ser criada em um thread STA. Você pode ver isso nos programas .NET, o ponto de entrada do thread de interface do usuário de um Windows Forms ou programa WPF tem o atributo [STAThread]. O modelo de apartamento para outros threads é definido pelo método Thread.SetApartmentState ().
Grandes partes do encanamento do Windows não funcionarão corretamente se o thread da interface do usuário não for STA. Notavelmente Drag + Drop, a área de transferência, diálogos do Windows como OpenFileDialog, controles como WebBrowser, aplicativos de automação de interface do usuário como leitores de tela. E muitos servidores COM, como o Office.
Um requisito difícil para um thread STA é que ele nunca deve bloquear e deve bombear um loop de mensagem. O loop de mensagem é importante porque é o que COM usa para empacotar uma chamada de método de interface de um thread para outro. Embora o .NET facilite as chamadas de empacotamento (Control.BeginInvoke ou Dispatcher.BeginInvoke, por exemplo), na verdade é uma coisa muito complicada de fazer. O thread que executa a chamada deve estar em um estado conhecido. Você não pode simplesmente interromper um thread arbitrariamente e forçá-lo a fazer uma chamada de método, o que causaria problemas de reentrância horríveis. Um thread deve estar "ocioso", não ocupado executando qualquer código que esteja alterando o estado do programa.
Talvez você possa ver aonde isso leva: sim, quando um programa está executando o loop de mensagem, ele está ocioso. O empacotamento real ocorre por meio de uma janela oculta que COM cria, ele usa PostMessage para que o procedimento de janela dessa janela execute o código. No tópico da STA. O loop de mensagem garante que esse código seja executado.
fonte
A "bomba de mensagens" é uma parte central de qualquer programa do Windows responsável por enviar mensagens em janelas para as várias partes do aplicativo. Este é o núcleo da programação da IU do Win32. Por causa de sua onipresença, muitos aplicativos usam a bomba de mensagem para passar mensagens entre módulos diferentes, razão pela qual os aplicativos do Office serão interrompidos se forem executados sem nenhuma interface do usuário.
A Wikipedia tem uma descrição básica .
fonte
John está falando sobre como o sistema Windows (e outros sistemas baseados em janela - X Window , Mac OS original ....) implementam interfaces de usuário assíncronas usando eventos por meio de um sistema de mensagens.
Nos bastidores de cada aplicativo, há um sistema de mensagens em que cada janela pode enviar eventos para outras janelas ou ouvintes de eventos - isso é implementado adicionando uma mensagem à fila de mensagens. Há um loop principal que sempre executa olhando para essa fila de mensagens e, em seguida, despacha as mensagens (ou eventos) para os ouvintes.
O artigo da Wikipedia Message loop no Microsoft Windows mostra o código de exemplo de um programa básico do Windows - e como você pode ver no nível mais básico, um programa do Windows é apenas a "bomba de mensagem".
Então, para juntar tudo. O motivo pelo qual um programa do Windows projetado para oferecer suporte a uma IU não pode atuar como um serviço é porque ele precisa do loop de mensagens em execução o tempo todo para habilitar o suporte à IU. Se você implementá-lo como um serviço conforme descrito, ele não será capaz de processar o tratamento de eventos assíncronos internos.
fonte
No COM , uma bomba de mensagem serializa e desserializa as mensagens enviadas entre apartamentos. Um apartamento é um miniprocesso no qual os componentes COM podem ser executados. Os apartamentos vêm em modos single threaded e free threaded. Os apartamentos de thread único são principalmente um sistema legado para aplicativos de componentes COM que não oferecem suporte a multi-threading. Eles eram normalmente usados com o Visual BASIC (já que não suportava código multithread) e aplicativos legados.
Eu acho que o requisito de bomba de mensagem para o Word deriva da API COM ou de partes do aplicativo que não são thread-safe. Lembre-se de que os modelos de threading e de coleta de lixo .NET não funcionam bem com o COM pronto para uso. COM tem um mecanismo de coleta de lixo muito simplista e um modelo de threading que exige que você faça as coisas da maneira COM. O uso dos PIAs padrão do Office ainda exige que você feche explicitamente as referências de objeto COM, portanto, você precisa controlar cada identificador COM criado. Os PIAs também criarão coisas nos bastidores, se você não tomar cuidado.
A integração .NET-COM é um tópico por si só, e existem até livros escritos sobre o assunto. Até mesmo o uso de APIs COM para Office em um aplicativo de área de trabalho interativo exige que você passe por muitos obstáculos e certifique-se de que as referências sejam liberadas explicitamente.
Pode-se presumir que o Office não é seguro para threads, portanto, você precisará de uma instância separada do Word, Excel ou outros aplicativos do Office para cada thread. Você teria que incorrer na sobrecarga inicial ou manter um pool de threads. Um pool de threads teria que ser testado meticulosamente para garantir que todas as referências COM foram lançadas corretamente. Até mesmo iniciar e encerrar instâncias exige que você certifique-se de que todas as referências sejam liberadas corretamente. Deixar de pontuar seus is e cruzar seus t aqui resultará em um grande número de objetos COM mortos e até mesmo instâncias inteiras do Word vazando.
fonte
Wikipedia sugere que significa o loop de evento principal do programa .
fonte
Acho que essa discussão do Canal 9 tem uma boa explicação sucinta:
fonte