メッセージループは、ネイティブのWindowsプログラムに存在する小さなコードです。おおよそ次のようになります。
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GetMessage()Win32 APIは、Windowsからメッセージを取得します。プログラムは通常、その時間の99.9%を費やし、Windowsが何か興味深いことが起こったことを知らせるのを待っています。TranslateMessage()は、キーボードメッセージを翻訳するヘルパー関数です。DispatchMessage()は、ウィンドウプロシージャがメッセージとともに呼び出されることを保証します。
すべてのGUI対応の.NETプログラムにはメッセージループがあり、Application.Run()によって開始されます。
Officeへのメッセージループの関連性はCOMに関連しています。OfficeプログラムはCOM対応プログラムであり、Microsoft.Office.Interopクラスはこのように機能します。COMは、COMコクラスに代わってスレッドを処理します。これにより、COMインターフェイスで行われる呼び出しが常に正しいスレッドから行われることが保証されます。ほとんどのCOMクラスは、レジストリにThreadingModelを宣言するレジストリキーを持っています。最も一般的なもの(Officeを含む)では、「アパートメント」を使用します。つまり、インターフェイスメソッドを呼び出す唯一の安全な方法は、クラスオブジェクトを作成したのと同じスレッドから呼び出すことです。言い換えると、ほとんどのCOMクラスはスレッドセーフではありません。
すべてのCOM対応スレッドはCOMアパートメントに属しています。シングルスレッドアパートメント(STA)とマルチスレッドアパートメント(MTA)の2種類があります。アパートメントスレッドのCOMクラスは、STAスレッドで作成する必要があります。これは.NETプログラムで確認できます。WindowsフォームまたはWPFプログラムのUIスレッドのエントリポイントには[STAThread]属性があります。他のスレッドのアパートメントモデルは、Thread.SetApartmentState()メソッドによって設定されます。
UIスレッドがSTAでない場合、Windowsの配管の大部分が正しく機能しません。特にドラッグアンドドロップ、クリップボード、OpenFileDialogのようなWindowsダイアログ、WebBrowserのようなコントロール、スクリーンリーダーのようなUIオートメーションアプリ。そして、Officeのような多くのCOMサーバー。
STAスレッドの厳しい要件は、メッセージループをブロックしてはならず、ポンプループする必要があることです。メッセージループは重要です。COMがこれを使用して、あるスレッドから別のスレッドへのインターフェイスメソッド呼び出しをマーシャリングします。.NETはマーシャリング呼び出しを簡単にします(たとえば、Control.BeginInvokeまたはDispatcher.BeginInvoke)が、実際には非常にトリッキーな作業です。呼び出しを実行するスレッドは、既知の状態である必要があります。スレッドを任意に中断して強制的にメソッド呼び出しを強制することはできません。これは恐ろしい再入問題を引き起こします。スレッドは「アイドル」である必要があり、プログラムの状態を変更するコードの実行でビジー状態ではありません。
おそらく、それがどこにつながるかを見ることができます:はい、プログラムがメッセージループを実行しているとき、それはアイドルです。実際のマーシャリングは、COMが作成する隠しウィンドウを介して行われ、PostMessageを使用して、そのウィンドウのウィンドウプロシージャにコードを実行させます。STAスレッド上。メッセージループにより、このコードが実行されます。