Что такое насос сообщений?
В этой теме (опубликованной около года назад) обсуждаются проблемы, которые могут возникнуть при запуске Word в неинтерактивном сеансе. (Довольно сильный) совет, данный там, не должен делать этого. В одном сообщении говорится: "Все API-интерфейсы Office предполагают, что вы запускаете Office в интерактивном сеансе на рабочем столе с монитором, клавиатурой и мышью и, что наиболее важно, насосом сообщений". Я не уверен, что это такое. (Я программировал на C# только около года; мой другой опыт программирования был в основном с ColdFusion.)
Обновить:
Моя программа проходит через большое количество файлов RTF, чтобы извлечь две части информации, использованной для построения номера медицинского заключения. Вместо того, чтобы пытаться понять, как работают инструкции по форматированию в RTF, я решил просто открыть их в Word и вытащить текст оттуда (фактически не запуская GUI). Иногда программа зависала в процессе обработки одного файла и оставляла открытым поток Word, прикрепленный к этому документу (мне все еще нужно выяснить, как закрыть этот файл). Когда я перезапустил программу, конечно, я получил уведомление, что существует поток, использующий этот файл, и я хотел открыть копию только для чтения? Когда я сказал "да", графический интерфейс Word неожиданно появился из ниоткуда и начал обрабатывать файлы. Мне было интересно, почему это произошло; но, может быть, когда диалоговое окно всплыло, насос сообщений начал выдвигать основной графический интерфейс в Windows?
6 ответов
Цикл сообщений - это небольшой фрагмент кода, который существует в любой родной программе Windows. Это выглядит примерно так:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Win32 API 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, чтобы оконная процедура этого окна выполняла код. На нити СТА. Цикл сообщений обеспечивает выполнение этого кода.
"Насос сообщений" является основной частью любой программы Windows, которая отвечает за отправку оконных сообщений в различные части приложения. Это ядро программирования Win32 UI. Из-за его повсеместного распространения многие приложения используют насос сообщений для передачи сообщений между различными модулями, поэтому приложения Office прерываются, если они запускаются без какого-либо пользовательского интерфейса.
Википедия имеет базовое описание.
Джон говорит о том, как система Windows (и другие оконные системы - X Window, оригинальная Mac OS....) реализуют асинхронные пользовательские интерфейсы, используя события через систему сообщений.
За кулисами для каждого приложения есть система обмена сообщениями, где каждое окно может отправлять события другим окнам или прослушивателям событий - это реализуется путем добавления сообщения в очередь сообщений. Существует основной цикл, который всегда выполняется, просматривая эту очередь сообщений и затем отправляя сообщения (или события) слушателям.
В статье Википедии цикл сообщений в Microsoft Windows показывает пример кода базовой программы Windows - и, как вы можете видеть на самом базовом уровне, программа Windows - это просто "насос сообщений".
Итак, чтобы собрать все это вместе. Причина, по которой программа Windows, разработанная для поддержки пользовательского интерфейса, не может выступать в качестве службы, заключается в том, что ей требуется постоянная работа цикла сообщений для включения поддержки пользовательского интерфейса. Если вы реализуете его как службу, как описано, он не сможет обрабатывать внутреннюю асинхронную обработку событий.
В COM насос сообщений сериализует и десериализует сообщения, отправленные между квартирами. Квартира - это мини-процесс, в котором могут быть запущены компоненты COM. Квартиры бывают однопоточными и свободными. Однопоточные квартиры в основном являются устаревшей системой для приложений COM-компонентов, которые не поддерживают многопоточность. Они обычно использовались с Visual BASIC (так как он не поддерживает многопоточный код) и устаревшими приложениями.
Я полагаю, что требование прокачки сообщений для Word проистекает либо из COM API, либо из частей приложения, не являющихся потокобезопасными. Имейте в виду, что модели потоков .NET и сборки мусора не очень хорошо работают с COM из коробки. COM имеет очень упрощенный механизм сборки мусора и многопоточную модель, которая требует, чтобы вы работали по-COM. Использование стандартных Office PIA все еще требует явного отключения ссылок на COM-объекты, поэтому вам необходимо отслеживать каждый созданный дескриптор COM. PIA также будут создавать вещи за сценой, если вы не будете осторожны.
Интеграция.NET-COM - это целая тема, и даже есть книги, написанные на эту тему. Даже использование COM API для Office из приложения для интерактивного рабочего стола требует, чтобы вы перепрыгивали через обручи и следили за тем, чтобы ссылки были явно освобождены.
Office можно считать поточно-небезопасным, поэтому для каждого потока вам потребуется отдельный экземпляр Word, Excel или других приложений Office. Вам придется взять на себя начальные накладные расходы или поддерживать пул потоков. Пул потоков должен быть тщательно проверен, чтобы убедиться, что все ссылки COM были правильно освобождены. Даже запуск и закрытие экземпляров требует от вас правильного освобождения всех ссылок. Если вы не укажете свои "я" и пересечете свои "я" здесь, это приведет к большому количеству мертвых COM-объектов и даже целым экземплярам Word, которые будут пропущены.
Википедия предполагает, что это означает основной цикл программы.
Я думаю, что у этого обсуждения на 9 канале есть хорошее краткое объяснение:
Этот процесс связи между окнами становится возможным благодаря так называемому Windows Message Pump. Думайте о Насосе сообщений как о сущности, которая обеспечивает взаимодействие между окнами приложений и рабочим столом.