Цикл сообщений - это небольшой фрагмент кода, который существует в любой родной программе Windows. Это выглядит примерно так:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
API Win32 GetMessage () получает сообщение из Windows. Ваша программа обычно проводит там 99,9% времени, ожидая, пока Windows сообщит, что произошло что-то интересное. TranslateMessage () - вспомогательная функция, которая переводит сообщения клавиатуры. DispatchMessage () гарантирует, что оконная процедура вызывается с сообщением.
Каждая программа .NET с графическим интерфейсом имеет цикл обработки сообщений, запускаемый Application.Run ().
Актуальность цикла сообщений для Office связана с COM. Офисные программы - это программы с поддержкой COM, так работают классы Microsoft.Office.Interop. COM заботится о многопоточности от имени COM-класса, это гарантирует, что вызовы, сделанные на COM-интерфейсе, всегда делаются из правильного потока. Большинство COM-классов имеют раздел реестра в реестре, который объявляет их ThreadingModel, безусловно, наиболее распространенные (включая Office) используют «Квартиру». Это означает, что единственным безопасным способом вызова метода интерфейса является выполнение вызова из того же потока, который создал объект класса. Или, другими словами, большинство классов COM не являются поточно-ориентированными.
Каждый поток с поддержкой COM принадлежит квартире COM. Есть два вида, однопоточные квартиры (STA) и многопоточные квартиры (MTA). Класс COM с поточной квартирой должен быть создан в потоке STA. Это можно увидеть в программах .NET, точка входа потока пользовательского интерфейса Windows Forms или WPF-программы имеет атрибут [STAThread]. Модель квартиры для других потоков задается методом Thread.SetApartmentState ().
Большие части сантехники Windows не будут работать правильно, если поток пользовательского интерфейса не является STA. В частности, Drag + Drop, буфер обмена, диалоговые окна Windows, такие как OpenFileDialog, элементы управления, такие как WebBrowser, приложения автоматизации пользовательского интерфейса, такие как программы чтения с экрана. И многие COM-серверы, такие как Office.
Жестким требованием к потоку STA является то, что он никогда не должен блокировать и должен прокачивать цикл сообщений. Цикл сообщений важен, потому что это то, что COM использует для перенаправления вызова метода интерфейса из одного потока в другой. Хотя .NET упрощает маршалинг-вызовы (например, Control.BeginInvoke или Dispatcher.BeginInvoke), сделать это очень сложно. Поток, который выполняет вызов, должен находиться в известном состоянии. Вы не можете просто произвольно прервать поток и заставить его выполнить вызов метода, что вызовет ужасные проблемы повторного входа. Поток должен быть "бездействующим", не занятым выполнением любого кода, который изменяет состояние программы.
Возможно, вы можете увидеть, к чему это приведет: да, когда программа выполняет цикл обработки сообщений, она простаивает. Фактическое маршалинг происходит через скрытое окно, которое создает COM, оно использует PostMessage, чтобы оконная процедура этого окна выполняла код. На нити СТА. Цикл сообщений обеспечивает выполнение этого кода.