Eine Nachrichtenschleife ist ein kleiner Code, der in jedem nativen Windows-Programm vorhanden ist. Es sieht ungefähr so aus:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Die GetMessage () Win32-API ruft eine Nachricht von Windows ab. Ihr Programm verbringt normalerweise 99,9% seiner Zeit dort und wartet darauf, dass Windows ihm mitteilt, dass etwas Interessantes passiert ist. TranslateMessage () ist eine Hilfsfunktion, die Tastaturmeldungen übersetzt. DispatchMessage () stellt sicher, dass die Fensterprozedur mit der Nachricht aufgerufen wird.
Jedes GUI-fähige .NET-Programm verfügt über eine Nachrichtenschleife, die von Application.Run () gestartet wird.
Die Relevanz einer Nachrichtenschleife für Office hängt mit COM zusammen. Office-Programme sind COM-fähige Programme. So funktionieren die Microsoft.Office.Interop-Klassen. COM kümmert sich um das Threading im Auftrag einer COM-Coclass. Es stellt sicher, dass Anrufe, die über eine COM-Schnittstelle getätigt werden, immer vom richtigen Thread aus erfolgen. Die meisten COM-Klassen haben einen Registrierungsschlüssel in der Registrierung, der ihr ThreadingModel deklariert. Die bei weitem häufigsten (einschließlich Office) verwenden "Apartment". Dies bedeutet, dass der einzige sichere Weg zum Aufrufen einer Schnittstellenmethode darin besteht, den Aufruf von demselben Thread aus durchzuführen, der das Klassenobjekt erstellt hat. Oder anders ausgedrückt: Die meisten COM-Klassen sind bei weitem nicht threadsicher.
Jeder COM-fähige Thread gehört zu einer COM-Wohnung. Es gibt zwei Arten, Single Threaded Apartments (STA) und Multi Threaded Apartments (MTA). Auf einem STA-Thread muss eine COM-Klasse mit Apartment-Thread erstellt werden. Sie können dies wieder in .NET-Programmen sehen. Der Einstiegspunkt des UI-Threads eines Windows Forms- oder WPF-Programms hat das Attribut [STAThread]. Das Apartmentmodell für andere Threads wird mit der Thread.SetApartmentState () -Methode festgelegt.
Große Teile der Windows-Installation funktionieren nicht ordnungsgemäß, wenn der UI-Thread nicht STA ist. Insbesondere Drag + Drop, die Zwischenablage, Windows-Dialoge wie OpenFileDialog, Steuerelemente wie WebBrowser, UI-Automatisierungs-Apps wie Screenreader. Und viele COM-Server wie Office.
Eine harte Anforderung für einen STA-Thread ist, dass er niemals blockieren und eine Nachrichtenschleife pumpen muss. Die Nachrichtenschleife ist wichtig, da COM damit einen Schnittstellenmethodenaufruf von einem Thread zum anderen marshallt. Obwohl .NET das Marshalling von Aufrufen vereinfacht (z. B. Control.BeginInvoke oder Dispatcher.BeginInvoke), ist dies eine sehr schwierige Aufgabe. Der Thread, der den Aufruf ausführt, muss sich in einem bekannten Zustand befinden. Sie können einen Thread nicht einfach willkürlich unterbrechen und ihn zu einem Methodenaufruf zwingen, der schreckliche Probleme beim Wiedereintritt verursachen würde. Ein Thread sollte "inaktiv" sein und keinen Code ausführen, der den Status des Programms verändert.
Vielleicht können Sie sehen, wohin das führt: Ja, wenn ein Programm die Nachrichtenschleife ausführt, ist es inaktiv. Das eigentliche Marshalling erfolgt über ein verstecktes Fenster, das COM erstellt. Es verwendet PostMessage, damit die Fensterprozedur dieses Fensters Code ausführt. Auf dem STA-Thread. Die Nachrichtenschleife stellt sicher, dass dieser Code ausgeführt wird.