UIを他のスレッドから直接操作すると、下記のようなExceptionが発生する。
System.InvalidOperationException
有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'textBox1' がアクセスされました
UIはUIスレッドからしか操作できないため、このExceptionが発生する。
この問題を解決するためには、Control.Invoke()メソッドを使用して、UI操作を適切なスレッド(UIスレッド)で行う必要がある。
以下の例では、SetLabelメソッドを使用して、UI上のラベル(label)を他のスレッドから安全に更新する方法を示す。
/// <summary>
/// UI上のラベルを更新する(UIスレッド)
/// </summary>
private void SetLabel(string text)
{
if (this.InvokeRequired)
{
//別スレッドから実行されている場合、InvokeでUIスレッドに切り替えてメソッドを呼び直す
this.Invoke(new Action<string>(SetLabel), text);
}
else
{
label.Text = text;
}
}
上記のコードでは、InvokeRequiredプロパティを使用して、現在のスレッドがUIスレッドであるかを確認する。
他のスレッドからメソッドが呼ばれた場合、Invokeメソッドを使用して、UIスレッドでSetLabel()を再度呼び出し、ラベルの更新を行う。これにより、安全にUIを操作できるようになる。
Labelを更新したい他のスレッド(タスク)にはAction型でSetLabelメソッドを渡してあげればよい。