STAThreadとマルチスレッド


102

STAThreadに関するMSDNの記事から:

アプリケーションのCOMスレッドモデルがシングルスレッドアパートメント(STA)であることを示します。

(参考までに、それが記事全体です。)

シングルスレッドのアパート... OK、それは私の頭を超えました。また、アプリケーションがCOM相互運用機能を使用しない限り、この属性は実際には何もしないことをどこかで読みました。では、それは正確には何をするのでしょうか。また、マルチスレッドアプリケーションにどのような影響を与えるのでしょうか。マルチスレッドアプリケーション(スレッドTimerプールなどだけでなく、sを使用して非同期メソッドの呼び出しを行うものも含む)は、「安全のため」にMTAThreadを使用する必要がありますか?STAThreadとMTAThreadは実際には何をしますか?

回答:


60

アパートメントスレッドはCOMの概念です。COMを使用しておらず、呼び出すAPIのいずれもCOMを「内部」で使用している場合は、アパートメントについて心配する必要はありません。

アパートを意識する必要がある場合は、詳細が少し複雑になることがあります。おそらく簡略化されたバージョンでは、STAとしてタグ付けされたCOMオブジェクトはSTAThreadで実行する必要があり、MTAとマークされたCOMオブジェクトはMTAスレッドで実行する必要があります。これらのルールを使用して、COMはこれらの異なるオブジェクト間の呼び出しを最適化し、不要な場所でのマーシャリングを回避できます。


7
それは単純化しすぎです。マルチスレッドオブジェクトは、どのスレッドでも実行できます。。アパートは、オブジェクトが唯一の彼らが作成されたアパートで実行できるスレッド
1800年の情報を

28
STAスレッドのSTAオブジェクトからMTAオブジェクトへの呼び出しは、MTAスレッドにマーシャリングされます(MTAオブジェクトがフリースレッドマーシャラーを実装していない場合)。私が言ったように、詳細は複雑になる可能性があります。(私は数年前からCOMチームに所属していました苦笑い
ブルース・

9
COMを直接使用していない場合でも、これに注意する必要がある場合があります。グラフィカルウィンドウを表示する場合、スレッドはシングルスレッドアパートメントモデルを使用する必要があります。これが、[STAThread]が常にWindowsフォームアプリケーションのメインメソッドの上に表示される理由です。
ジャスティンエティエ

6
フォントやファイルのダイアログのようなものは、知らないうちにCOMを使用できませんか?私はそれらが内部で行うと思いますが、それはほとんどすべてのWindowsフォームアプリケーションがSTAThreadの設定を必要とすることを意味しませんか?実際にはCOMプログラミングを行っていないので、私の素朴な仮定は許してください。
ブレットライアン

4
興味がある人のためのより詳細な回答:stackoverflow.com/questions/4154429/apartmentstate-for-dummies
jgauffin

3

これにより、CoInitializeCOINIT_APARTMENTTHREADEDをパラメーターとして指定して呼び出されることが保証されます。COMコンポーネントやActiveXコントロールを使用しない場合は、まったく影響がありません。もしそうなら、それは一種の重要なことです。

アパートメントスレッド化されたコントロールは事実上シングルスレッド化されており、それらへの呼び出しは、作成されたアパートメントでのみ処理できます。

MSDNの詳細:

シングルスレッドアパートメント(STA)で作成されたオブジェクトは、アパートメントのスレッドからのみメソッド呼び出しを受信するため、呼び出しはシリアル化され、メッセージキューの境界にのみ到達します(Win32関数のPeekMessageまたはSendMessageが呼び出された場合)。

マルチスレッドアパートメント(MTA)のCOMスレッドで作成されたオブジェクトは、いつでも他のスレッドからのメソッド呼び出しを受信できる必要があります。オブジェクトのデータを保護するために、クリティカルセクション、セマフォ、ミューテックスなどのWin32同期プリミティブを使用して、マルチスレッドオブジェクトのコードに何らかの形式の同時実行制御を実装します。

ニュートラルスレッドアパートメント(NTA)で実行するように構成されているオブジェクトが、STAまたはMTAのいずれかにあるスレッドによって呼び出されると、そのスレッドはNTAに転送されます。このスレッドがその後CoInitializeExを呼び出すと、呼び出しは失敗し、RPC_E_CHANGED_MODEを返します。


MSDNの記事はCOMの観点からは役に立ちますが、.NETが呼び出されたときに教えてもらえますか CoInitialize()が、STAThread属性/ に応答してれるApartmentState。注:MSDNの記事はこちら:CoInitializeEx関数
jrh

する スレッド> SetApartmentは使用CoInitialize()内部?ずっと下のSTAThread属性をトレースしましたが、証跡は冷たくなっています(のソースが見つかりませんThread::SetApartment)。thread.h(COM thread.h)のThreadクラスはどこかに文書化されていますか?それはMFC、ATLなどですか?
jrh

@jrh申し訳ありませんが、それ以上の詳細はわかりません
1800情報

-15

STAThreadは、C#GUIプロジェクトのMain関数の前に作成されます。プログラムが単一のスレッドを作成できるようにするだけです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.