2009-08-15 10 views
6

最近、メイン/ UIスレッドではなく、別のスレッドでフォームを表示したいという状況に遭遇しました。私はスレッドプールスレッドを使用しました。フォームはRCW(COMコンポーネント用)をホストしました。フォームをインスタンス化すると、スレッドはSTAでなければならないという例外がありました。私はSTAとしてアパートの状態を設定しようとしました。しかし、それはどちらもうまくいかなかった。私は最終的にスレッドを明示的に作成することになり、それがうまくいった(私はShowDialogを使用し、メイジポンプを作成する必要はない)。なぜ私たちはThreadPoolスレッドのアパートの状態を変更できないのですか?また、ShowDialogが使用されているときにメッセージポンプを必要としないのはなぜですか?

EDIT:

  • 私は、スレッドプールのスレッドが MTAであることを知っています。しかし、なぜSTAに設定できないのですか? これについてはちょっと不思議です。ちょうど で私の頭をポップ
  • もう一つの問題は、:にShowDialog()(
    表示形式に)

答えて

8

アパートメントは、CoInitializeEx()の呼び出しによって選択されます。スレッドプール内のスレッドはすでにその呼び出しを行っており、呼び出し後にアパートメントを変更することはできません。スレッドプールは、MTAが理にかなって選ぶだろう

は、それが後に、すべてのワーカースレッドとして意図されており、マーシャリングする必要があるメソッドの呼び出しによってブロックされるべきではありません。シングルスレッドアパートメントを選択するには、メッセージループをポンピングするという追加要件があります。あなたが決してスレッドプールスレッドが行うとは思わない何か。それはCOMが別のスレッドで行われる呼び出しをマーシャリングするために使用する車両だから

メッセージループが必要です。その呼び出しはSTAスレッドに「注入」されなければなりません。これは、スレッドが既知の静止状態にある場合にのみ可能です。もしそうでなければ、そのような呼び出しは大きな再突入問題を引き起こすでしょう。スレッドがループをポンピングしている場合でも時々実行されます。

にShowDialog()は、独自のメッセージループを開始しますので、あなたは)Application.Run(とメッセージループを自分でポンプする必要はありませんでした。それがモダリティを得る方法です。ネストされたループは、ダイアログが閉じるとすぐに終了します。

+0

答えをありがとう。 ShowDialog()が独自のメッセージループを開始すると言うリンクを指すことができます。 –

+0

http://www.red-gate.com/products/reflector推奨します。 –

+0

ありがとうございます。 Application.RunDialog(これは)トリックを行います。 –

8

を使用しているのに、なぜ私たちは、あなたが頼るべきではありません
メッセージポンプを必要としませんスレッドプールスレッドの固有の動作。一般に、スレッドプール内のスレッドは、あなたが知らないうちにCLRによっていつでも置き換えることができます。スレッドプールスレッドは、単純なタスク、好ましくは短命のスレッドで使用することを目的としています。

あなたがスレッドの設定よりきめの細かい制御を持っているしたい場合は、専用のスレッドを作成する必要があります。アパートの状態を設定することは、これの完璧な例です。


理論上の理由に加えて、試みているものには実際的な問題があります。 2番目のスレッドでフォームをホストしても機能しません(余分な作業を余儀なくされることはありません)。フォームは、メッセージポンプと同じスレッドで実行する必要があります。そうしないと、ウィンドウメッセージは表示されず、正しく更新されません。

このスレッド用に完全なメッセージポンプを実装する場合は、別のスレッドでフォームを作成できますが、通常はワークアイテムをバックグラウンドスレッドに配置し、非同期プログラミング手法を使用してUIを維持してくださいスレッドに応答します。

+0

答えをありがとう。 "スレッドプール内のスレッドは、いつでも知りませんが、CLRによっていつでも置き換えることができます。これを知らなかったそれはどういう意味ですか? –

+1

スレッドプールは、プログラムの実行中にスレッドを作成して破棄します。スレッドプールには固定数のスレッドしか(必然的に)存在しません。 .NET 4のスレッドプールは、この点でさらに柔軟性があります。これには、アプリケーションの実行時にスレッドを生成して破壊するような、仕事盗みなどのためのあらゆる種類の新しいツールがあります。 –

+0

oh..yes私は完全にメッセージポンプについて認識しています。したがって、スレッドプールスレッドまたは新しいスレッド経由でフォームを作成するには、そのスレッドにメッセージポンプを接続する必要があります。しかし、私はフォームを表示するためにShowDialog()を使用し、それはブロッキングコールであるためメッセージポンプを必要としません。 実際、私は、なぜThreadPoolスレッドのアパートの状態をSTAに変更できないのか不思議に思っていました。おかげさまで –

関連する問題