さまざまな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節でロックが必要ですか?
ありがとう、キーは、スレッドがLoadReports()を実行したときに完全にロードされていないフォームでした。 InvokeRequiredへの不要な呼び出しもすべて削除しました。 – Zamboni