すべてのサーバー側コードに対してConfigureAwaitを呼び出すのがベストプラクティスです。質問する

すべてのサーバー側コードに対してConfigureAwaitを呼び出すのがベストプラクティスです。質問する

サーバー側コード (つまり一部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にはSynchronizationContextASP.NET Core を使用している場合は、使用するかどうかは関係ありませんConfigureAwait(false)

ASP.NET の「Full」または「Classic」などの場合でも、この回答の残りの部分は適用されます。

元の投稿 (Core ASP.NET 以外):

ASP.NET チームによるこのビデオには、asyncASP.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紹介ブログ投稿

おすすめ記事