c# - Illegal Cross Thread Operation例外の解決策はありますか?

Translate

C#でデータをバインドすると、データを変更するスレッドによってコントロールも変更されます。ただし、このスレッドがコントロールが作成されたスレッドでない場合は、不正なクロススレッド操作の例外が発生します。

これを防ぐ方法はありますか?

This question and all comments follow the "Attribution Required."

すべての答え

Translate

次のようなことができるはずです。

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ブロックが不要になり、コードが強化されます。

ソース
Translate

移行するテストケースがないため、このソリューションを保証することはできませんが、さまざまなスレッドでプログレスバーを更新する(デリゲートを使用する)ために使用されるシナリオと同様のシナリオがここでは適しているようです。

public delegate void DataBindDelegate();
public DataBindDelegate BindData = new DataBindDelegate(DoDataBind);

public void DoDataBind()
{
    DataBind();
}

データバインディングを特定のスレッドで実行する必要がある場合は、そのスレッドに作業を任せてください。

ソース
Translate

スレッド呼び出しが「不正」である場合(つまり、DataBind呼び出しが、呼び出し元のスレッドで作成されなかったコントロールに影響を与える場合)、DataBindの決定/準備がで行われなくても、デリゲートを作成する必要があります。コントロール作成スレッド、それらの結果として生じる変更(つまり、DataBind())は次のようになります。

次のように、ワーカースレッドから私のコードを呼び出します。

this.BindData.Invoke();

これにより、元のスレッドがバインディングを実行します。これは(コントロールを作成したスレッドであると想定して)機能するはずです。

ソース
Translate

WPFとSilverlightでは、バインディングインフラストラクチャがUIスレッドへの切り替えを処理します。

ソース