私はちょうど次のようなコードに出くわしました:
_var task = Task.Run(async () => { await Foo.StartAsync(); });
task.Wait();
_
(いいえ、Foo.StartAsync()
の内部構造はわかりません)。私の最初の反応はasync
/await
を取り除き、次のように書き直します。
_var task = Foo.StartAsync();
task.Wait();
_
それは正しいでしょうか、そうではありませんか(ここでも、Foo.StartAsync()
についてまったく何も知りません)。 This に答える 違いは何ですか-Task.Runで 'async'アクションデリゲートを実行する... 意味があるかもしれない場合があることを示しているようです、しかしそれはまた「実を言うと、私はそんなに多くのシナリオを見たことがありません...」
通常、意図された_Task.Run
_の使用法は実行することです非UIスレッドのCPUバインドコード。そのため、async
デリゲートと共に使用することは非常にまれですが、それは可能です(たとえば、非同期部分とCPUバインド部分の両方を持つコードの場合)。
ただし、それは意図された使用法です。私はあなたの例で考える:
_var task = Task.Run(async () => { await Foo.StartAsync(); });
task.Wait();
_
元の作者が非同期コードで同期的にブロックしようとしている可能性がはるかに高く、(ab)_Task.Run
_を使用して その状況で一般的なデッドロックを回避する (私のブログで説明しているように) 。
本質的には、私が brownfield非同期コードに関する記事 で説明した「スレッドプールハック」のように見えます。
bestソリューションは、_Task.Run
_またはWait
を使用しないことです:
_await Foo.StartAsync();
_
これにより、async
がコードベース全体に拡大するようになります。これは最善の方法ですが、現在、開発者にとって許容できない量の作業が発生する可能性があります。これがおそらく、前任者がTask.Run(..).Wait()
を使用した理由です。
主にそうです。
このようなTask.Run
の使用は、非同期メソッドの実行方法を理解していない人が主に使用します。
ただし、違いがあります。 Task.Run
の使用は、ThreadPool
スレッドで非同期メソッドを開始することを意味します。
これは、asyncメソッドの同期部分(最初のawaitの前の部分)が大きく、呼び出し側がそのメソッドがブロックされていないことを確認したい場合に役立ちます。
これは、たとえばSynchronizationContext
がない場合など、現在のコンテキストから「抜け出す」ためにも使用できます。