web-dev-qa-db-ja.com

.NET Coreで.Result()または.Wait()の代わりにawaitを使用して正当化する方法は?

.NET Coreの開始以来、コンソールアプリ、関数アプリ、ASP.NETなどは非同期メソッドで同期コンテキストを使用していません(そのため、スレッドプールに直接同期しています)。

つまり、非同期メソッドの後に.Result()または.Wait()を使用しても、デッドロックは発生せず、パフォーマンス(スレッドの予約)にのみ影響します。ある場所から別の場所へのデータの読み取りと書き込みのみを行うスレッド化されたビジネスアプリケーション。

現在、ほとんどの開発者は.Result().Wait()を使用しています。これは、個別のawaitキーワードよりも見栄えが良いためです。また、プロジェクトのサイズは非常に小さいため、それらのプロジェクトの唯一の開発者です。

awaitキーワードを使用してどのように正当化できますか他の開発者がそれを使用するインセンティブがない場合?この動作が大規模なプロジェクトで問題を引き起こす可能性があることがわかります。

質問を編集しました。コメントを参照してください。

3
kor_

非同期/待機のポイントを逃しました

デッドロックで開発者を苛立たせるために作成されたのではありません。 CPUベースではないタスクが完了するのを待つ間、処理能力を解放するために作成されました。

Dotnetcoreに同期コンテキストがないことで、予期しないデッドロックからあなたを救うかもしれませんが、それはまた、スレッドの枯渇を心配する必要があることを意味します。

Task.Wait()またはtask.Result()でスレッドをブロックするたびに、アプリが処理に使用できるスレッドが1つ少なくなります。

Awaitを使用すると、そのスレッドが解放され、他のタスクで使用できるようになります。

以前はデッドロックが発生していたはずなのに、今ではスレッドが不足しています。

https://docs.Microsoft.com/en-us/aspnet/core/performance/performance-best-practices?view=aspnetcore-3.

実際にコードをテストせずに要点を示すために、思考実験の危険を冒します。物事は見かけほど単純ではないため、常にリスクがあります。

Eコマースサイトがあるとします。顧客はバックエンドへのapi呼び出しを介して注文します。 APIは注文をデータベースに保存しますが、注文によっては外部APIを介した不正チェックが必要になることがあります。

通常の運用では、1分間に数回の注文があり、サイトは正常に動作しています。ただし、クリスマスセール中は1秒あたりの注文を受け取ります。

4コアマシンで実行していて、APIが不正チェックでブロックしている場合は、スレッドが3つに減り、最初の注文が完了する前に別の3つの不正チェックオーダーが到着すると、キューが開始されます。 APIはロックされています。

遅い注文は完了してスレッドを解放しますが、追いつく要求のバックログがあり、それらの要求のそれぞれにタイムアウトがあります。

そのため、ピーク時に顧客は「エラーは注文できませんでした:タイムアウト」と表示し始めます

代わりに詐欺の呼び出しを待つと、呼び出しが行われたときにスレッドがすぐに解放され、応答が返されるまで要求を処理できます。 1秒に1オーダーしかなく、4スレッドで十分です。

8
Ewan

私の意見では、最大の要因は、Result/Waitメンバーを使用すると、作成しているメソッドが非同期ではなく同期になることです。つまり、同期関数を作成することを明示的に決定し、そのモデルに適合するように呼び出すメソッドのセマンティクスを変更します。つまり、メソッドを呼び出す必要があるすべてのメソッドは、非同期で実行するのではなく、同期で実行する必要があります。これは、awaitキーワードを使用して他の関数の非同期動作を許可した場合に可能になります。あなたは繁殖を呼びかけています.

作成したメソッド、特にパブリックメソッドは、後で別の開発者がどのように使用するかがわからないため、これは重要です。現在、スレッド化とパフォーマンスが問題になる場所ではないかもしれませんが、将来のコンシューマーがメソッドを使用しているどこかに関連している可能性があり、それを書いている時点ではわかりません。何らかの理由で絶対にメソッドを同期させる必要がない限り、awaitを使用してメソッドをasyncにすることで、呼び出している他のメソッドの非同期の性質をメソッドを介して伝播させることもできます。

2

お気づきのように、「明らかな利点」はパフォーマンスに影響を与えることです。どの非同期メソッドを使用しているかは質問から明らかではありませんが、パフォーマンスが問題にならない場合は、それらのメソッドの同期バージョン(多くのAPIで利用可能)を使用するだけで、非同期にはまったく対処できません。ただし、これがASP.NETのコンテキストであり、暗黙的な同時実行が発生している(複数の要求を処理する)場合は、要求処理のパフォーマンスを妨げないようにasync/awaitを使用することをお勧めします。

0
Yuli Bonner