2

私は伝統的に、何らかの理由で C# の BackgroundWorkers に多くの問題を抱えています。彼らのコンセプトは本当に私を困惑させているように見えるので、これがかなり基本的な問題であり、簡単に修正できることを願っています...

.NET リモート処理を使用してやり取りする 2 つのフォームがあります。現在、Form1 の設定を変更すると、Form2 で何かが変更され、うまく機能しています。ただし、今は同じことを別の方法で機能させる必要があり (Form2 で何かを変更すると Form1 が更新されます)、同じ方法では実行できません (設計上の制限により、Form2 に変更を送信させることはできません)。 Form1 に)。現在、Form1 で BackgroundWorker を使用して、各サブコントロール (Form1 に配置されている) で 'Update()' メソッドを常に呼び出そうとしています。これらの各コントロールには、Form2 から同等の設定の現在の状態を取得し、それ自体を更新する手段があります (これはうまく機能します。'Update()' メソッドは Form1 の初期化で動作していることがわかります)。

ここで私の問題が発生します。BackgroundWorker が各フォームで常に「Update()」を呼び出す方法が不明だったので、「DoWork()」メソッドに「while(true)」ループがあり、その中で BackgroundWorker が「Update」を呼び出します。 ()' 各サブコントロールのメソッドを実行し、非常に短い時間スリープしてから繰り返します。

このようにすると、「InvalidOperationException was unhandled by user code」というエラーが表示され、「クロススレッド操作が無効です: コントロール 'comboBox_BGColor' は、作成されたスレッド以外のスレッドからアクセスされました。」これで、基本的にこれが何を意味するのかがわかり、なぜそれが起こったのか理解できましたが、どうすればいいのか、または希望どおりに機能させるために変更する方法がわかりません。これについて、または私が BackgroundWorker を使用している方法についてのヒントはありますか? 情報をありがとう、そしてこれを読むために時間を割いてくれてありがとう!

4

3 に答える 3

3

UI コントロールにはスレッド アフィニティがあります。UI スレッド以外のスレッドからコントロール (読み取りまたは書き込み) に触れないでください。が主BackgroundWorkerに UIと対話している場合は、コントロールだけを使用した方がよいでしょう。これにより、または何度も呼び出す必要がなくなります。TimerInvokeBeginInvoke

ただし、一般的には、UI に変更を反映させる変更通知イベント ( または のいずれFooChangedか) とイベント ハンドラーを使用して、より「オブザーバー」ベースの設計を好みます。INotifyPropertyChanged

于 2010-11-18T14:24:24.287 に答える
1

バックグラウンドワーカーの代わりにタイマー制御が必要です

于 2010-11-18T14:25:05.993 に答える
1

受け取っている例外は、BackgroundWorker のスレッド内Update()から直接呼び出す (プライマリ スレッドで 1 つ以上のフォームを変更する)ことの結果です。_DoWork

メソッドを使用するBackgroundWorker場合:

  • ワーカーの.WorkerReportsProgressプロパティをに設定しますtrue
  • ループを実行するときは、ワーカーのメソッドを使用してワーカーのイベント ハンドラー.ReportProgress()をトリガーします。_ProgressChanged
  • _ProgressChangedイベント ハンドラーは、フォームのメソッドの呼び出しをUpdate()安全に実行できます。

ワーカーの使用をやめた場合 (特に、バックグラウンド ワーカーがこのループ専用に存在する場合)、Marc の標準イベント ハンドラーの提案に従うことをお勧めします。Timerそのルートは、外部ループまたはコントロールを追加するよりも、プロセッサーのオーバーヘッドが少なくなります (ただし、現在は最小限である場合とそうでない場合があります) 。

どちらのルートでも、クロススレッド例外に対処する必要があります。

于 2010-11-18T16:45:36.403 に答える