別のスレッドでフォームのインスタンスを初期化しますか?

c# multithreading winforms

心配

WinFormsのメインスレッド以外のスレッドにコントロール/フォームを作成するのは悪い習慣ですか? 私は、あるスレッドが別のスレッドで作成されたコントロール上で何かを変更できないことだけがルールだと思ったのですか。

シナリオ

私はいくつかのワーカースレッドを持つアプリケーションを持っています。 それらのワーカースレッドはそれぞれ*フォームの*自分自身のインスタンス*を表示することがあります。 そのフォームに起こるすべてのことはそのスレッド内に留まり、他のスレッドはそのフォームインスタンスに何かをしようとしません。 このフォームにはいくつかのTelerikコントロールがあり、それらを新しいバージョンにアップグレードすると、ここで説明するようなエラーが発生します。

System.Reflection.TargetInvocationExceptionが処理されませんでしたMessage = "呼び出しのターゲットによって例外がスローされました。" Source = "mscorlib" StackTrace:at System.RuntimeMethodHandle._InvokeMethodFast(Object target、Object []引数、SignatureStruct

質問

メインアプリケーションスレッド以外のスレッドでフォームインスタンスを作成することは許容できますか、それともそのスレッドへの* all *コールを整列化する必要がありますか これはTelerikのコントロールをアップグレードするまで機能していたので、今は新しいバグがあるのか​​、それともずっと間違っていたのです。

助けてください!

  1  0


ベストアンサー

スタックトレースから、Telerikコントロールはおそらくグローバル(静的)変数を通して、単一の `System.Drawing.Image`インスタンスを共有しているように見えます。 異なるスレッドでコントロールをインスタンス化するため、イメージは一度に複数のスレッドからアクセスされることになりますが、これはサポートされていません。 グローバル変数を使用する従来のコード(非GUI)についても同様の問題があります。

あなたの質問に答えるには:はい、あなたがしていることは受け入れ可能ですが、そのようなユースケースは十分にまれであり、3rdpartyコントロールのベンダーがそれをサポートしないと決定するかもしれません。 最も簡単な解決法(あるいはあなたがソースを持っているならあなたは)は、次のようにグローバル変数を見つけてそれらをスレッドローカルにすることです。

[ThreadStatic]
static int foo;

これにより、各スレッドはそれぞれ独自の「グローバル」変数を取得し、それらを互いに分離します。

2


フォームを表示しようとする各スレッドで、 Application.Run()(またはそのオーバーロードの1つ)を呼び出す必要があります。 それ以外は、スレッド間で変更を加えない限り、問題ないはずです。

注目に値するのは、 `Application.Run(Form)`オーバーロードを使うと、フォームが閉じられたときに関数呼び出しの後に実行が継続されるということです。

1


タイトルとURLをコピーしました