Pętla komunikatów to mały fragment kodu, który istnieje w każdym rodzimym programie Windows. Z grubsza wygląda to tak:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GetMessage () Win32 API pobiera komunikat z systemu Windows. Twój program zazwyczaj spędza tam 99,9% czasu, czekając, aż system Windows powie mu, że wydarzyło się coś interesującego. TranslateMessage () to funkcja pomocnicza, która tłumaczy komunikaty klawiatury. DispatchMessage () zapewnia wywołanie procedury okna wraz z komunikatem.
Każdy program .NET obsługujący graficzny interfejs użytkownika ma pętlę komunikatów, jest ona uruchamiana przez Application.Run ().
Znaczenie pętli komunikatów dla pakietu Office jest związane z COM. Programy pakietu Office są programami obsługującymi COM, tak działają klasy Microsoft.Office.Interop. COM zajmuje się wątkami w imieniu koklasy COM, zapewnia, że wywołania wykonywane przez interfejs COM są zawsze wykonywane z właściwego wątku. Większość klas COM ma klucz rejestru w rejestrze, który deklaruje ich ThreadingModel, zdecydowanie najpopularniejsze (w tym Office) używają nazwy „Apartment”. Oznacza to, że jedynym bezpiecznym sposobem wywołania metody interfejsu jest wykonanie wywołania z tego samego wątku, który utworzył obiekt klasy. Albo inaczej: zdecydowanie większość klas COM nie jest bezpieczna wątkowo.
Każdy wątek z włączonym COM należy do apartamentu COM. Istnieją dwa rodzaje mieszkań, apartamenty jednowątkowe (STA) i apartamenty wielowątkowe (MTA). W wątku STA należy utworzyć klasę COM z wątkami mieszkania. Można to zobaczyć z powrotem w programach .NET, punkt wejścia wątku interfejsu użytkownika programu Windows Forms lub WPF ma atrybut [STAThread]. Model apartamentu dla innych wątków jest ustawiany przez metodę Thread.SetApartmentState ().
Duże części instalacji systemu Windows nie będą działać poprawnie, jeśli wątek interfejsu użytkownika nie jest STA. W szczególności Drag + Drop, schowek, okna dialogowe systemu Windows, takie jak OpenFileDialog, elementy sterujące, takie jak WebBrowser, aplikacje automatyzacji interfejsu użytkownika, takie jak czytniki ekranu. I wiele serwerów COM, takich jak Office.
Trudnym wymogiem dla wątku STA jest to, że nigdy nie powinien blokować i musi pompować pętlę komunikatów. Pętla komunikatów jest ważna, ponieważ właśnie tego używa COM do organizowania wywołania metody interfejsu z jednego wątku do drugiego. Chociaż .NET ułatwia organizowanie wywołań (na przykład Control.BeginInvoke lub Dispatcher.BeginInvoke), w rzeczywistości jest to bardzo trudne. Wątek, który wykonuje wywołanie, musi być w dobrze znanym stanie. Nie możesz po prostu arbitralnie przerwać wątku i zmusić go do wywołania metody, co spowodowałoby okropne problemy z ponownym włączaniem. Wątek powinien być „bezczynny”, wolny od wykonywania kodu, który zmienia stan programu.
Być może widzisz, do czego to prowadzi: tak, gdy program wykonuje pętlę komunikatów, jest bezczynny. Właściwe kierowanie odbywa się za pośrednictwem ukrytego okna, które tworzy COM, używa PostMessage, aby procedura okna tego okna wykonywała kod. W wątku STA. Pętla komunikatów zapewnia, że ten kod działa.