2010-12-31 21 views
4

さまざまなWinFormコントロールを更新する2つの非UIスレッドを持つコードを継承しました。
コードはInvokeRequiredとInvokeを使用してUIを更新しています。しかし、私はまだ間違いがあります:クロススレッド操作が有効でない:コントロール 'lvReports'が作成されたスレッド以外のスレッドでアクセスされました。Winform:複数のスレッド同時にUIを更新する

私は競合状態に対処していると思いますし、以下の方法でロックを導入する必要があると思いますが、UIを非UIスレッドから安全に更新する方法については数多くの例がありますレースシナリオで同じコントロールを更新する2つのスレッドを処理する方法の例や議論。

私の質問は、以下のコードを書き換えて、競合条件が与えられたときにUIを適切に更新し、UI以外のスレッドからUIを更新する必要があることです。

// two separate theads call this method in a instance of a WinForm 
private void LoadReports() 
{ 
    if (this.InvokeRequired) 
    { 
    this.Invoke(new MethodInvoker(this.LoadReports)); 
    } 
    else 
    { 
    // some code removed to keep exampe simple... 
    SetCtlVisible(lvReports, true); 

    if (this.InvokeRequired) 
    { 
     this.Invoke((MethodInvoker)delegate { lvReports.Refresh(); }); 
    } 
    else 
    { 
     lvReports.Refresh(); 
    } 
    } 
} 

delegate void SetVisibleCallback(Control ctl, bool visible); 
private void SetCtlVisible(Control ctl, bool visible) 
{ 
    if (ctl.InvokeRequired) 
    { 
    SetVisibleCallback d = new SetVisibleCallback(SetCtlVisible); 
    ctl.Invoke(d, new object[] { ctl, visible }); 
    } 
    else 
    { 
    ctl.Visible = visible; 
    } 
} 

ここではいくつかの考えがあります: はいつでもctl.InvokeRequired異なるthis.InvokeRequiredていますか? 2番目のInvokeRequiredテストが最初に必要ですか? 最初のInvokeRequiredを保持する場合、SetCtlVisibleの実装が必要ですか? 最初のInvokeRequiredを削除し、else節のすべてのコードを保持する必要がありますか? else節でロックが必要ですか?

答えて

9

このようにInvokeRequiredを使用すると、アンチパターンが発生します。 このメソッドがスレッドから呼び出されることを知っていれば、InvokeRequiredは常に真でなければなりません。

これで問題をトラブルシューティングできます。それが偽であるなら、真剣に間違っていることがあります。例外をスローすると、デバッガが停止し、デバッガがなぜ正しく動作しないのかを知ることができます。そして、常にInvoke()を呼び出すと、残りのLoadReports()を行うちょっとしたヘルパーメソッドが呼び出されます。

また、残りのコードで間違って使用していることにも注意してください。 LoadReports()の残りの部分がUIスレッド上で実行されていることがわかっている場合は、Invoke()を使用しました。 SetCtlVisible()の中を含め、再度テストする必要はありません。

爆弾を取得する典型的な理由は、フォームのウィンドウが作成される前にスレッドがLoadReports()を実行している時間が短すぎるためです。それを連動させる必要があります。フォームのLoadイベントはシグナルです。

+0

ありがとう、キーは、スレッドがLoadReports()を実行したときに完全にロードされていないフォームでした。 InvokeRequiredへの不要な呼び出しもすべて削除しました。 – Zamboni

関連する問題