Un bucle de mensaje es un pequeño fragmento de código que existe en cualquier programa nativo de Windows. Más o menos se parece a esto:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
La API GetMessage () Win32 recupera un mensaje de Windows. Su programa normalmente pasa el 99,9% de su tiempo allí, esperando que Windows le diga que ha ocurrido algo interesante. TranslateMessage () es una función auxiliar que traduce los mensajes del teclado. DispatchMessage () asegura que se llame al procedimiento de ventana con el mensaje.
Cada programa .NET habilitado para GUI tiene un bucle de mensaje, es iniciado por Application.Run ().
La relevancia de un bucle de mensajes para Office está relacionada con COM. Los programas de Office son programas compatibles con COM, así es como funcionan las clases Microsoft.Office.Interop. COM se encarga del subproceso en nombre de una coclase COM, se asegura de que las llamadas realizadas en una interfaz COM siempre se realicen desde el subproceso correcto. La mayoría de las clases COM tienen una clave de registro en el registro que declara su ThreadingModel; las más comunes (incluida Office) usan "Apartamento". Lo que significa que la única forma segura de llamar a un método de interfaz es haciendo la llamada desde el mismo hilo que creó el objeto de clase. O para decirlo de otra manera: la mayoría de las clases COM no son seguras para subprocesos.
Cada subproceso habilitado para COM pertenece a un apartamento COM. Hay dos tipos, apartamentos de un solo subproceso (STA) y un apartamento de subprocesos múltiples (MTA). Se debe crear una clase COM de subproceso de apartamento en un subproceso de STA. Puede ver esto en los programas .NET, el punto de entrada del subproceso de la interfaz de usuario de un programa de Windows Forms o WPF tiene el atributo [STAThread]. El modelo de apartamento para otros subprocesos se establece mediante el método Thread.SetApartmentState ().
Gran parte de la plomería de Windows no funcionará correctamente si el hilo de la interfaz de usuario no es STA. En particular, arrastrar y soltar, el portapapeles, cuadros de diálogo de Windows como OpenFileDialog, controles como WebBrowser, aplicaciones de automatización de la interfaz de usuario como lectores de pantalla. Y muchos servidores COM, como Office.
Un requisito estricto para un subproceso STA es que nunca debe bloquearse y debe bombear un bucle de mensaje. El bucle de mensajes es importante porque eso es lo que COM usa para ordenar una llamada de método de interfaz de un hilo a otro. Aunque .NET facilita la clasificación de llamadas (Control.BeginInvoke o Dispatcher.BeginInvoke por ejemplo), en realidad es algo muy complicado de hacer. El hilo que ejecuta la llamada debe estar en un estado conocido. No puede simplemente interrumpir arbitrariamente un hilo y forzarlo a realizar una llamada a un método, eso causaría horribles problemas de reentrada. Un hilo debe estar "inactivo", no ocupado ejecutando ningún código que esté mutando el estado del programa.
Quizás pueda ver a dónde conduce eso: sí, cuando un programa está ejecutando el bucle de mensajes, está inactivo. La clasificación real tiene lugar a través de una ventana oculta que crea COM, utiliza PostMessage para que el procedimiento de ventana de esa ventana ejecute código. En el hilo de STA. El bucle de mensajes asegura que este código se ejecute.