C# でデータをバインドすると、データを変更するスレッドによってコントロールも変更されます。ただし、このスレッドがコントロールが作成されたスレッドでない場合は、Illegal Cross Thread Operation 例外が発生します。
これを防ぐ方法はありますか?
C# でデータをバインドすると、データを変更するスレッドによってコントロールも変更されます。ただし、このスレッドがコントロールが作成されたスレッドでない場合は、Illegal Cross Thread Operation 例外が発生します。
これを防ぐ方法はありますか?
次のようなことができるはずです。
if (control.InvokeRequired)
{
control.Invoke(delegateWithMyCode);
}
else
{
delegateWithMyCode();
}
InvokeRequired は、正しいスレッドにいるかどうかを確認するための Controls のプロパティです。Invoke は、正しいスレッドでデリゲートを呼び出します。
更新:実際、私の最後の仕事では、次のようなことをしました:
private void SomeEventHandler(Object someParam)
{
if (this.InvokeRequired)
{
this.Invoke(new SomeEventHandlerDelegate(SomeEventHandler), someParam);
}
// Regular handling code
}
これにより、else ブロックが不要になり、コードが強化されます。
テスト ケースがないため、この解決策を保証することはできませんが、別のスレッドでプログレス バーを更新する (デリゲートを使用する) のと同様のシナリオが適していると思われます。
public delegate void DataBindDelegate();
public DataBindDelegate BindData = new DataBindDelegate(DoDataBind);
public void DoDataBind()
{
DataBind();
}
データ バインディングを特定のスレッドで行う必要がある場合は、そのスレッドに任せてください。
スレッド呼び出しが「不正」である場合 (つまり、DataBind 呼び出しが、呼び出し元のスレッドで作成されていないコントロールに影響を与える場合)、デリゲートを作成して、DataBind の決定/準備が行われない場合でも、デリゲートを作成する必要があります。コントロールを作成するスレッド、それらの結果の変更 (つまり、DataBind()) が行われます。
次のように、ワーカー スレッドから私のコードを呼び出します。
this.BindData.Invoke();
これにより、元のスレッドがバインディングを実行し、(コントロールを作成したスレッドであると仮定して) 動作するはずです。
WPF と Silverlight では、バインディング インフラストラクチャが UI スレッドへの切り替えを処理します。