C#2.0とMethodInvokerデリゲートを使用して、GUIアプリケーションがGUIスレッドまたはワーカースレッドからイベントを受信しています。
次のパターンを使用して、フォームでイベントを処理します。
private void SomeEventHandler(object sender, EventArgs e)
{
MethodInvoker method = delegate
{
uiSomeTextBox.Text = "some text";
};
if (InvokeRequired)
BeginInvoke(method);
else
method.Invoke();
}
このパターンを使用して実際のUIコードを複製することはありませんが、この方法が適切かどうかはわかりません。
特に、ライン
method.Invoke()
呼び出しに別のスレッドを使用しますか、それともGUIスレッドのメソッドへの直接呼び出しに多少変換しますか?
method.Invoke()
呼び出しは、現在実行中のスレッドでデリゲートを実行します。 BeginInvoke(method)
を使用すると、デリゲートがGUIスレッドで確実に呼び出されます。
これは、GUIスレッドと他のスレッドの両方から同じメソッドを呼び出すことができる場合に、コードの重複を回避する正しい方法です。
個人的に私はこの方法が好きです:
private void ExecuteSecure(Action a)
{
if (InvokeRequired)
BeginInvoke(a);
else
a();
}
そして、次のようなワンライナーを書くことができます:
ExecuteSecure(() => this.Enabled = true);
バックグラウンドスレッドを使用していて、Control.IsHandleCreatedがfalseの場合、Control.InvokeRequiredはfalseを返すことに注意してください。アンマネージハンドルの作成をチェックするDebug.Assertでコードを保護します。
WinFormsの場合、Control.Invoke(Delegate)
を呼び出すと、UIのtheadのメッセージポンプにメッセージが送信されます。次に、スレッドはメッセージを処理し、デリゲートを呼び出します。処理が完了すると、Invoke
はブロックを停止し、呼び出しスレッドがコードの実行を再開します。
同じスレッドで呼び出しを行います。コードをステップ実行して確認できます。そのアプローチには何の問題もありません。