サーバー側コード (つまり一部ApiController
) があり、関数が非同期 (つまり戻り値を返すTask<SomeObject>
) である場合、呼び出す関数を常に待機することがベスト プラクティスと見なされますかConfigureAwait(false)
?
スレッド コンテキストを元のスレッド コンテキストに戻す必要がないため、パフォーマンスが向上すると読んだことがあります。ただし、ASP.NET Web API では、要求が 1 つのスレッドで受信され、何らかの関数を待機して呼び出すと、関数ConfigureAwait(false)
の最終結果を返すときに別のスレッドに移動する可能性がありますApiController
。
私が話していることの例を以下に入力しました。
public class CustomerController : ApiController
{
public async Task<Customer> Get(int id)
{
// you are on a particular thread here
var customer = await GetCustomerAsync(id).ConfigureAwait(false);
// now you are on a different thread! will that cause problems?
return customer;
}
}
ベストアンサー1
アップデート: ASP.NET CoreにはSynchronizationContext
ASP.NET Core を使用している場合は、使用するかどうかは関係ありませんConfigureAwait(false)
。
ASP.NET の「Full」または「Classic」などの場合でも、この回答の残りの部分は適用されます。
元の投稿 (Core ASP.NET 以外):
ASP.NET チームによるこのビデオには、async
ASP.NET での使用に関する最良の情報が記載されています。
スレッド コンテキストを元のスレッド コンテキストに戻す必要がないため、パフォーマンスが向上すると読みました。
これは UI アプリケーションに当てはまります。UI アプリケーションでは、「同期」する必要がある UI スレッドが 1 つだけあります。
ASP.NET では、状況はもう少し複雑です。async
メソッドが実行を再開すると、ASP.NET スレッド プールからスレッドを取得します。 を使用してコンテキスト キャプチャを無効にするとConfigureAwait(false)
、スレッドはそのままメソッドの実行を継続します。コンテキスト キャプチャを無効にしない場合は、スレッドは要求コンテキストに再度入り、メソッドの実行を継続します。
したがって、ConfigureAwait(false)
ASP.NET でのスレッド ジャンプは節約されませんが、要求コンテキストの再入力は節約されますが、これは通常非常に高速です。要求の少量の並列処理を実行しようとしている場合は役立つConfigureAwait(false)
可能性がありますが、実際には、TPL はほとんどのシナリオに適しています。
ただし、ASP.NET Web API では、要求が 1 つのスレッドで受信され、何らかの関数を待機して ConfigureAwait(false) を呼び出すと、ApiController 関数の最終結果を返すときに別のスレッドに移動する可能性があります。
実際には、 を実行するだけでawait
それが実現できます。async
メソッドが に達するとawait
、メソッドはブロックされますが、スレッドはスレッド プールに戻ります。メソッドを続行する準備ができたら、任意のスレッドがスレッド プールから取得され、メソッドを再開するために使用されます。
ASP.NET で唯一の違いはConfigureAwait
、メソッドを再開するときにそのスレッドが要求コンテキストに入るかどうかです。
詳しい背景情報はMSDNの記事SynchronizationContext
と私async
紹介ブログ投稿。