web-dev-qa-db-ja.com

C#は1つまたは複数のバックグラウンドワーカーを作成する必要がありますか?

私はそのような偶然のプログラマーの1人なので、プログラミングのベストプラクティスに関する知識があまりありません。

現在4バックグラウンドワーカーを使用しているアプリケーションがあります。

だから私はそれらを宣言します:

private BackgroundWorker bw1;
private BackgroundWorker bw2;
private BackgroundWorker bw3;
private BackgroundWorker bw4;

次に、それらを構成します。

bw1 = new BackgroundWorker();
bw1.WorkerReportsProgress = true;
bw1.DoWork += new DoWorkEventHandler(bw1_DoWork);
bw1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw1_RunWorkerCompleted);
bw1.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

bw2 = new BackgroundWorker();
bw2.WorkerReportsProgress = true;
bw2.DoWork += new DoWorkEventHandler(bw2_DoWork);
bw2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw2_RunWorkerCompleted);
bw2.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

bw3 = new BackgroundWorker();
bw3.WorkerReportsProgress = true;
bw3.DoWork += new DoWorkEventHandler(bw3_DoWork);
bw3.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw3_RunWorkerCompleted);
bw3.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

bw4 = new BackgroundWorker();
bw4.WorkerReportsProgress = true;
bw4.DoWork += new DoWorkEventHandler(bw4_DoWork);
bw4.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw4_RunWorkerCompleted);
bw4.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

次に、bw1.RunWorkerAsync()、bw2.RunWorkerAsync()などを使用します...

事は私がそれらを同時に呼び出すことは決してないということです、彼らはかなり直線的な方法で異なるポイントで呼び出されます。

だから私の質問は、多くの「事前設定された」バックグラウンドワーカーを持っているのか、それともDoWorkイベントとRunWorkerCompletedイベントを私がやりたいことに応じて変更するのが良いのかということです。

24
Alex

アーキテクチャの観点からは、バックグラウンドタスクごとに個別のバックグラウンドワーカーを用意するのが最善です。これは、クラスの別のタスクとは論理的に無関係です。

24
Maxim V. Pavlov

通常、私はまったく異なるパターンでバックグラウンドワーカーを使用します。それぞれのイベントハンドラーを含め、最初にそれらをすべて一度に定義するのではなく、必要な処理を実行するときに、その場で作成します。

public void SomeEventHandlerMaybe(object sender, EventArgs e) {
  // do something

  var bw = new BackgroundWorker();
  bw.ReportsProgress = true;
  bw.DoWork += delegate {
    // do work. You can use locals from here
  };
  bw.ProgressChanged += delegate { ... };
  bw.RunWorkerCompleted += delegate {
    // do something with the results.
  };
  bw.RunWorkerAsync();
}

そんな感じ。バックグラウンドワーカーで、またはバックグラウンドワーカーで何かを実行するすべてのコードが1か所にあり、おおよそ正しい順序でもあるという利点があります。

27
Joey

一般に、システムでのより効率的なリソースの使用に役立つ場合は、複数のスレッドを使用するのが妥当です。 CPU集中型のタスクでは、CPUコアごとに1つのスレッドが出発点として適しています。 IO集中的なタスクの場合、確かにそれより多くのものを持つことができます。

.NET 4を使用する柔軟性がある場合は、BackgroundWorkerではなく Task Parallel Library を調べます。デフォルトでは、より簡単なプログラミングモデルを提供することに加えて、同時に実行するスレッドの数について比較的賢明な決定を行います。

5
Eric J.

BackgroundWorkerを使用して処理を行うということは、別のスレッドで処理を行うことを意味します。したがって、マルチスレッドが必要ない場合は、別個のバックグラウンドワーカーは必要ありません。各ワーカーを開始した後で完了を待つ場合、ワーカーは1つだけです。また、コードの重複の一部を削除する可能性があります...

0
Amittai Shapira

なんらかの計算目的でワーカーを実行します。 1つの呼び出しの計算が使用されているか、何らかの方法で別の呼び出しに依存している場合、より良いパフォーマンスを達成するために、複数のワーカーを使用できます(これにより、これは測定の対象となりすぎるためです)。 4つのジョブを実行するだけで、メインUIをブロックしないように別のスレッドで実行する場合は、1人のワーカーで解決できます。

0
Tigran