web-dev-qa-db-ja.com

Async / await vs BackgroundWorker

過去数日間で、.net 4.5およびc#5の新機能をテストしました。

新しいasync/await機能が気に入っています。以前、レスポンシブUIを使用してバックグラウンドでより長いプロセスを処理するために BackgroundWorker を使用していました。

私の質問は次のとおりです。これらの素晴らしい新機能を導入した後、いつasync/awaitを使用する必要があり、 BackgroundWorker ?両方の一般的なシナリオはどれですか?

151
Tom

async/awaitは、BackgroundWorkerなどの構造を置き換えるように設計されています。確かにcan使用したい場合は、async/awaitを他のいくつかのTPLツールと一緒に使用して、そこにあるすべてのものを処理できるはずです。

どちらも機能するため、いつ使用するかは個人の好みに依存します。 yoの方が速いですか? yoが理解しやすいのは何ですか?

72
Servy

これは良い紹介です: http://msdn.Microsoft.com/en-us/library/hh191443.aspx Threadsセクションはまさにあなたが探しているものです:

非同期メソッドは、非ブロッキング操作を目的としています。非同期メソッドのawait式は、待機中のタスクの実行中に現在のスレッドをブロックしません。代わりに、式はメソッドの残りを継続としてサインアップし、非同期メソッドの呼び出し元に制御を返します。

Asyncおよびawaitキーワードは、追加のスレッドを作成しません。非同期メソッドは独自のスレッドで実行されないため、非同期メソッドはマルチスレッドを必要としません。メソッドは現在の同期コンテキストで実行され、メソッドがアクティブな場合にのみスレッドの時間を使用します。 Task.Runを使用してCPUにバインドされた作業をバックグラウンドスレッドに移動できますが、バックグラウンドスレッドは、結果が利用可能になるのを待っているプロセスには役立ちません。

非同期プログラミングへの非同期ベースのアプローチは、ほとんどすべてのケースで既存のアプローチよりも望ましいです。特に、IOにバインドされた操作の場合、このアプローチはBackgroundWorkerよりも優れています。コードが単純であり、競合状態から保護する必要がないためです。 Task.Runとの組み合わせでは、非同期プログラミングはTask.Runがスレッドプールに転送する作業からコードを実行する調整の詳細を分離するため、CPUにバインドされた操作ではBackgroundWorkerよりも優れています。

20
TommyN

BackgroundWorker は、.NET 4.5で廃止として明示的にラベル付けされます。

MSDN記事 「非同期と待機を使用した非同期プログラミング(C#とVisual Basic)」

非同期プログラミングへの非同期ベースのアプローチほとんどの場合、既存のアプローチよりも望ましい。特に、このアプローチは BackgroundWorkerIOバインド操作の場合よりも優れています。コードが単純であり、競合状態から保護する必要がないためです。 Task.Runとの組み合わせでは、非同期プログラミングは BackgroundWorkerCPUバインド操作の場合よりも優れています。非同期プログラミングはコードを実行する調整の詳細を作業から分離するためです。 that Task.Runスレッドプールへの転送

UPDATE

  • @ eran-otzap のコメントに対する回答:
    「IOバインド操作の場合、コードが単純であり、競合状態から保護する必要がないため」どのような競合状態が発生する可能性がありますか、例を挙げてください。 」

この質問は別の投稿として投稿されるべきでした。

ウィキペディアには、 racing 状態の良い説明があります。その必要な部分はマルチスレッドであり、同じMSDN記事 AsyncとAwaitを使用した非同期プログラミング(C#とVisual Basic) からのものです。

非同期メソッドは、非ブロッキング操作を目的としています。非同期メソッドのawait式は、待機中のタスクの実行中に現在のスレッドをブロックしません。代わりに、式はメソッドの残りを継続としてサインアップし、非同期メソッドの呼び出し元に制御を返します。

Asyncおよびawaitキーワードは、追加のスレッドを作成しません。非同期メソッドは独自のスレッドで実行されないため、非同期メソッドはマルチスレッドを必要としません。メソッドは現在の同期コンテキストで実行され、メソッドがアクティブな場合にのみスレッドの時間を使用します。 Task.Runを使用してCPUにバインドされた作業をバックグラウンドスレッドに移動できますが、バックグラウンドスレッドは、結果が利用可能になるのを待っているプロセスには役立ちません。

非同期プログラミングへの非同期ベースのアプローチは、ほとんどすべてのケースで既存のアプローチよりも望ましいです。特に、IOにバインドされた操作の場合、このアプローチはBackgroundWorkerよりも優れています。コードが単純であり、競合状態から保護する必要がないためです。 Task.Runと組み合わせて、非同期プログラミングは、Task.Runがスレッドプールに転送する作業からコードを実行する調整の詳細を分離するため、CPUにバインドされた操作に対してBackgroundWorkerよりも優れています。

つまり、「asyncおよびawaitキーワードは、追加のスレッドを作成しません」。

1年前にこの記事を勉強していたときの自分の試みを思い出すことができる限り、同じ記事のコードサンプルを実行して遊んだ場合、非同期バージョンではないという状況にぶつかることがあります(変換しようとすることができます)自分自身に)無期限にブロックしてください!

また、具体的な例については、このサイトを検索できます。以下に例を示します。