2011-01-11 12 views
17

Visual Studioで空のWinFormsアプリケーションを作成すると、テンプレートにはメインアプリケーションクラスにSTAThreadという属性があります。なぜWinFormsアプリケーションはデフォルトでSTAThreadですか?

私はそれについていくつかのドキュメントを読んできましたが、私はそれを全く理解しているかどうかはわかりません。

は本当に私はそれについていくつか質問している:なぜ、この属性は

  1. が追加されますか?
  2. どういう意味ですか?
  3. この属性を削除するとどうなりますか?
+2

可能な複製:http://stackoverflow.com/questions/102437/why-do-all-winforms-programs-require-the-stathread-attribute –

+0

@Cody:はい、申し訳ありませんが、私はそれを見ましたが、IMHOこの答えは他のものよりずっと優れています。 –

+1

ええ、そうです。私はそれらの答えが幻想的ではなかったので、閉会に投票しませんでした。その質問から得られる最も重要な知識は、このリンクです。http://blogs.msdn.com/b/jfoscoding/archive/2005/04/07/406341.aspx –

答えて

12

1.この属性はなぜ追加されますか?

ActiveXオブジェクトモデルでは必須であるためです。また、ActiveXコントロールをWinFormにドロップすることもできます(互換性のためにそこにあります)。または、一部の.NETクラスでは、その属性を必要とするネイティブコントロールを使用します。

2.それはどういう意味ですか?

これは、スレッドがsingle-threaded apartment modelで実行されていることを意味します。

3.この属性を削除するとどうなりますか?

属性が削除された場合の動作は未定義です。プログラムがランダムに失敗することがあり、時には賢明なエラーメッセージが表示されることがあります。たとえば、今は動作してから、サービスパックで動作します。

+1

あなたが直面する最大の問題は、COM interopです。そして、あなたがこれをやっていない、気にしないとは言わないでください.Windowsは多くのことをカバーしています。 –

+0

少なくともWPFはMTAで動作することを拒否し、すぐに例外をスローします。 WinFormsでもそうすることができます。 – Joey

+1

ActiveXコントロールだけでなく、他にもたくさんのものがあります。クリップボード、ドラッグ+ドロップ、OpenFileDialogのようなシェルダイアログ。 COM APIをフードの下で使用する.NETラッパーのプラスロット。それはあなたが見ることができないが、STAスレッドでのみ正しく動作するCOM相互運用機能です。 CLRでも認識していますが、Thread.Join()はUIスレッドで呼び出されたときにメッセージループをポンピングします。 –

19

STAThreadAttributeが印加されると、an MSDN blogから

を引用し、それはシングルスレッドであることが、現在のスレッドのアパートメント状態を変化させます。 COMとスレッドに関する膨大な議論に慣れることなく、この属性は現在のスレッドとCOM経由で話したいスレッドとの間の通信メカニズムを保証します。使用している機能に応じて、Windowsフォームを使用している場合、オペレーティングシステムのコンポーネントと通信するためにCOM相互運用機能を使用している可能性があります。これの良い例は、クリップボードとファイルダイアログです。

+0

あなたの答えにブログへのリンクを入れるといいでしょう。 – GEOCHET

0

つまり、Windowsフォームプログラムはシングルスレッドのアパートメント状態を使用します。 MTAとフリースレッドアパートメントの状態はサポートされていません。

3

3.この属性を削除するとどうなりますか?

問題を示す簡単な例を追加します。

ボタンとOpenFileDialogで簡単なWinFormsアプリケーションを作成しました。ボタンをクリックすると、openFileDialogを示すスレッドが実行されます。私は、STAThreadの有無にかかわらずアプリを起動し、ボタンをクリックした結果は同じです。「クロススレッド操作が無効です:コントロール 'フォーム1」が作成されたスレッド以外のスレッドからアクセスされました。 違いがないように見えます。しかし、いいえ。予想通り、それは正常に動作STAThreadで

private void ShowOFD() 
{ 
    if (InvokeRequired) 
    { 
     BeginInvoke(new Action(ShowOFD)); 
     return; 
    } 

    openFileDialog1.ShowDialog(this); 
} 

は、その後、私は以下のメソッドを呼び出すことによってopenFileDialogを示す変更しました。 STAThreadを使用しない場合、例外がスローされます "現在のスレッドは、OLE呼び出しを行う前にシングルスレッドアパートメント(STA)モードに設定する必要があります。メイン関数にSTAThreadAttributeが設定されていることを確認してください。 「プロセスに」。

その後、私はデバッガなしで(ビジュアルスタジオから切り離された)アプリを何度も起動します。アプリがただ静かに閉じたとき、別の時に "vshostが動作を停止しました"というメッセージで閉じられたとき

関連する問題