.NET 4.5 を使用している場合は、一般的にTask
and/orをお勧めします。await
しかし、Task
BGW には 2 つの明確に異なるシナリオがあります。Task は、継続に連鎖できる一般的な短い非同期タスクに適しており、await は暗黙的に UI スレッドにマーシャリングするタスクに適しています。BGW は、UI の応答性に影響を与えない単一の長い操作に適しています。BGW をデザイン サーフェイスにドラッグ アンド ドロップし、ダブルクリックしてイベント ハンドラーを作成できます。別のスレッドにマーシャリングしたくない場合LongRunning
は、対処する必要はありません。ConfigureAwait
多くの人は、BGW の進行は よりも簡単だと感じていますIProgress<T>
。
「長時間の操作」シナリオで両方を使用する例を次に示します。
Task
質問は特に .NET 4.0 に言及しているため、UI に進行状況を提供しながら長い操作を実行するためにa を使用する単純なコードを次に示します。
startButton.Enabled = false;
var task = Task.Factory.
StartNew(() =>
{
foreach (var x in Enumerable.Range(1, 10))
{
var progress = x*10;
Thread.Sleep(500); // fake work
BeginInvoke((Action) delegate {
progressBar1.Value = progress;
});
}
}, TaskCreationOptions.LongRunning)
.ContinueWith(t =>
{
startButton.Enabled = true;
progressBar1.Value = 0;
});
同様のコードは次のBackgroundWorker
ようになります。
startButton.Enabled = false;
BackgroundWorker bgw = new BackgroundWorker { WorkerReportsProgress = true };
bgw.ProgressChanged += (sender, args) =>
{ progressBar1.Value = args.ProgressPercentage; };
bgw.RunWorkerCompleted += (sender, args) =>
{
startButton.Enabled = true;
progressBar1.Value = 0;
};
bgw.DoWork += (sender, args) =>
{
foreach (var x in Enumerable.Range(1, 10))
{
Thread.Sleep(500);
((BackgroundWorker)sender).ReportProgress(x * 10);
}
};
bgw.RunWorkerAsync();
.NET 4.5 を使用している場合は、.NET呼び出しProgress<T>
の代わりに を使用できます。4.5 以降では、次のようにするとより読みやすくなります。BeginInvoke
Task
await
startButton.Enabled = false;
var pr = new Progress<int>();
pr.ProgressChanged += (o, i) => progressBar1.Value = i;
await Task.Factory.
StartNew(() =>
{
foreach (var x in Enumerable.Range(1, 10))
{
Thread.Sleep(500); // fake work
((IProgress<int>) pr).Report(x*10);
}
}, TaskCreationOptions.LongRunning);
startButton.Enabled = true;
progressBar1.Value = 0;
UsingProgress<T>
は、コードが特定の UI フレームワーク (つまり の呼び出し) に結合されていないことを意味します。これは、特定の UI フレームワークからの切り離しを容易にするBeginInvoke
のとほぼ同じ方法です。BackgroundWorker
気にしない場合は、使用の複雑さを追加する必要はありませんProgress<T>
に関してはLongRunning
、Stephen Toub が言うように、「LongRunning を使用しないと他の作業の処理に長い遅延が発生することがパフォーマンス テストでわかった場合にのみ、LongRunning を使用するのが一般的です」。それを使用してください-追加の分析または常にパラメーターを追加することの「複雑さ」がありLongRunning
ます。LongRunning を使用しないということは、実行時間の長い操作に使用されるスレッド プール スレッドが他のより一時的なタスクに使用できなくなり、スレッド プールがこれらの一時的なタスクの 1 つの開始を遅らせ、別のスレッドを開始することを意味します (少なくとも2番目)。
フレームワークには、BGW (または EAP、または APM) が非推奨であることを明確に示す属性はありません。したがって、これらのものがいつどこで「時代遅れ」になるかを決めるのはあなた次第です。特に BGW には、依然として適用される非常に具体的な使用シナリオが常にありました。.NET 4.0 と 4.5 にはかなりまともな代替手段があります。しかし、BGWが「時代遅れ」だとは本当に思いません。
BackgroundWorker
常に useと言っているわけではありません。BackgroundWorker を自動的に非推奨にする前に考えてください。場合によっては、それがより良い選択かもしれません。