私はConfigureAwait(false)で非同期ライブラリメソッドを呼び出しています。しかし、私はまだデッドロックで終わる。 (ASP.NETコントローラAPIで使用しています) しかし、同じメソッドをTask.Run()にラップすると、正常に動作します。Task.Run()の動作中にConfigureAwait(false)が機能しないのはなぜですか?
ライブラリメソッドがConfigureAwaitを内部的に使用していない場合、ConfigureAwaitを追加してもライブラリ呼び出しで問題が解決されない場合、デッドロックが発生します(.Resultを使用してブロックします)。しかし、その場合、同じコンテキスト/スレッドで続行できないため、Task.Run()で動作するのはなぜですか。
このarticleはこれについて語ります。 Btw、私はStephen Clearyの記事をたくさん用意しています。しかし、なぜTask.Run()が動作するのは謎です。
コードスニペット:現在SynchronizationContext
を使用して継続を実行しようとしているので、最初の例で
// This Create Method results in Deadlock
public async Task<string> Create(MyConfig config)
{
Document doc = await Client.CreateDocumentAsync(CollectionUri, config).ConfigureAwait(false);
return doc.Id;
}
// Uses Task.Run() which works properly, why??
public string Create(MyConfig config)
{
Document doc = Task.Run(() => Client.CreateDocumentAsync(CollectionUri, config)).Result;
return doc.Id;
}
[HttpPost]
public ActionResult CreateConfig(MyConfig config)
{
string id = Create(config).Result;
return Json(id);
}
ConfigureAwait(false)を使用して、ThreadPoolを使用して継続を確実にする必要はありませんか?はい、CreateConfigメソッドを非同期にしました。しかし、Task.Run()が何の問題も生じない理由を正確に理解したかったのです。 –
@KrunalModi 'ConfigureAwait(false)'は、 'Client.CreateDocumentAsync'の呼び出しではなく、スレッドプールの使用を継続するよう設定します。 – Lukazoid
@KrunalModi内部的に別の非同期呼び出しを持つ非同期呼び出しで' ConfigureAwait'を使用するポイントがありません。 * ConfigureAwaitで使用されていません。 'ConfigureAwait(false)'は、*ほぼ*どこでも、特にライブラリで使用するべきです。 UI同期コンテキストで継続が実行されるべきであるため、トップレベルの呼び出し(UI同期コンテキストの呼び出し)だけが 'ConfigureAwait(false)'を必要としません。 'await Task.Run(()=> ...)'または 'await Task.Run(()=> ...)を使って' ConfigureAwait(false) 'を内部的に使用しないライブラリの場合ConfigureAwait(false ) 'は良い回避策です。 –