Um loop de mensagem é um pequeno trecho de código que existe em qualquer programa nativo do Windows. É mais ou menos assim:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
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.