それは素晴らしい用語ではありません。実際にはスレッドの動作を説明しています。スレッドは、STAとMTAのどちらかを選択して、CoInitializeEx()呼び出しでの動作をCOMに通知します。STAを使用することにより、スレッドは、スレッドセーフではないコードに適した方法で動作することを約束します。それがする難しい約束は次のとおりです。
- 実行をブロックしない
- メッセージループをポンピングします
MTAを使用するということは、スレッドがやりたいことを何でもできることを意味し、スレッドセーフではないコードをサポートするための努力をしません。
これは、COMオブジェクトが作成されるときに最初に重要になります。このようなオブジェクトには、実装するスレッドセーフの種類を説明するキーがレジストリに含まれています。ThreadingModelキー。このキーの最も一般的な値は「Apartment」(または欠落している)であり、COMにスレッド化をまったくサポートしておらず、オブジェクトに対するすべての呼び出しを同じスレッドから行う必要があることを伝えます。
そのようなオブジェクトを作成するスレッドがSTAにある場合、すべてが幸せです。結局のところ、スレッドはシングルスレッドオブジェクトをサポートすることを約束しました。スレッドがMTAにある場合は、問題があります。スレッドは、スレッドセーフをサポートしていないと述べましたが、スレッドセーフではないオブジェクトを作成しました。のCOMステップは、新しいスレッド、つまりスレッドセーフではないコードをサポートできるSTAスレッドを作成します。コードはオブジェクトへのプロキシを取得します。オブジェクトに対して行われたすべての呼び出しは、そのプロキシを通過します。プロキシコードは呼び出しをインターセプトし、作成されたSTAスレッドで実行するため、呼び出しがスレッドセーフな方法で行われるようになります。
ご想像のとおり、プロキシによって行われる作業は安くはありません。これには2つのスレッドコンテキストスイッチが含まれ、呼び出しを行うには関数の引数からスタックフレームを構築する必要があります。また、スレッドが呼び出しを実行する準備ができるまで待機する必要があります。これはマーシャリングと呼ばれ、マーシャリングする必要のない呼び出しを行うよりも3桁遅くなります。これはおそらく、STAスレッドに上記の2つの要件がある理由も説明しています。ブロックしている限り、マーシャリングされた呼び出しを行うことができず、デッドロックが発生する可能性が非常に高いため、ブロックできません。そして、メッセージループをポンピングする必要があります。そのループは、別のスレッドへの呼び出しの挿入を可能にするものです。
したがって、スレッドをMTAに参加させることは、プログラミングが簡単です。しかし、パフォーマンスには致命的です。STAは効率的です。