.Net 4.5の非同期プログラミングについて読んだときに、async
およびawait
キーワードを読みました- ここ 次の段落
非同期リクエストの処理
起動時に多数の同時要求が発生するか、バースト負荷がかかる(同時実行性が急激に増加する)Webアプリケーションでは、これらのWebサービス呼び出しを非同期にすると、アプリケーションの応答性が向上します。 非同期要求の処理には、同期要求と同じ時間がかかります。たとえば、リクエストが完了するのに2秒を必要とするWebサービス呼び出しを行う場合、リクエストは同期または非同期のどちらで実行されても2秒かかります。ただし、非同期呼び出し中、スレッドは、最初の要求が完了するまで待機している間、他の要求への応答をブロックされません。したがって、非同期要求は、長時間実行される操作を呼び出す同時要求が多数ある場合に、要求のキューイングとスレッドプールの増大を防ぎます。
大胆な言葉のために、非同期要求が同期要求と同じ時間を処理する方法を理解できませんでしたか?
例:
_public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
await Task.Delay(1000); //1 seconds delay
return 1;
}
_
LongRunningOperation()
はここでTask<int> longRunningTask = LongRunningOperation();
を呼び出す最初の行から実行を開始し、await
を呼び出すと値を返すことを理解しているため、私の観点からは非同期コードは同期よりも速く、そうですか?
MyMethod()
の実行に取り組んでいるメインスレッドは、LongRunningOperation()
が完了するまで待機することをブロックしていませんが、スレッドプールに戻って別のリクエストを処理することを理解しています。それを実行するためにLongRunningOperation();
に割り当てられた別のスレッドがありますか?
yesの場合、非同期プログラミングとマルチスレッドプログラミングの違いは何ですか?
更新:
コードがそのようになるとしましょう:
_public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
DoIndependentWork();
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
DoSomeWorkNeedsExecution();
await Task.Delay(1000); //1 seconds delay
return 1;
}
_
この場合、LongRunningOperation()
の実行中にDoIndependentWork()
が別のスレッドによって実行されますか?
非同期操作は高速ではありません。非同期的に(つまりawait Task.Delay(10000)
)または同期的に(つまりThread.Sleep(10000)
)10秒待つと、同じ10秒かかります。唯一の違いは、最初のスレッドは待機中にスレッドを保持しませんが、2番目のスレッドは待機します。
これで、タスクを起動し、すぐに完了するのを待たない場合、同じスレッドを使用して他の作業を行うことができますが、非同期操作の実行を「スピードアップ」しません。
var task = Task.Delay(10000);
// processing
await task; // will complete only after 10 seconds
2番目の質問について:Task.Delay
(他の真の非同期操作のように)スレッドを実行する必要がないため、 スレッドはありません です。 Task.Delay
は、起動するSystem.Threading.Timer
を使用して実装され、実行されるとイベントを発生させます。その間、実行するコードがないため、スレッドは必要ありません。
したがって、MyMethod
を実行していたスレッドがawait longRunningTask
に達すると、(longRunningTask
がまだ完了していない限り)解放されます。 ThreadPool
スレッドであった場合、ThreadPool
に戻り、アプリケーション内の他のコードを処理できます。
更新に関しては、フローは次のようになります。
MyMethod
は処理を開始しますLongRunningOperation
は処理を開始しますDoSomeWorkNeedsExecution
は呼び出しスレッドで実行されますawait
でLongRunningOperation
に到達したため、ホットタスクが返されます。DoIndependentWork
は同じ呼び出しスレッドによって実行されます(LongRunningOperation
はまだ「実行中」であり、スレッドは不要です)await
でMyMethod
に到達します。元のタスクが完了した場合、同じスレッドが同期的に続行し、そうでない場合は、最終的に完了するホットタスクが返されます。したがって、async-await
を使用しているという事実により、CPUを集中的に実行する作業を同期して待機することをブロックするスレッドを使用することができます。
以下の違いを考慮してください。
Thread.Sleep(1000);
そして
await Task.Delay(1000);
両方とも実行に1秒かかります。ただし、前者の場合、現在のスレッドはブロックされ(そのリソースはすべて役に立たなくなります)、後者の場合、現在のスレッドは有用な何か他のことを行うことができます(たとえば、別のリクエストを処理します)。
非同期性とは、命令の個々のシーケンスを高速化することではなく、同期コードがブロックする場合に実行できることです。
Re。 別の質問
解放されたスレッドは他のものに使用されます。操作が完了するまで、スレッドは割り当てられません。これは、基になるOS自体が非同期であるため可能です。上記の例では、内部で停止したスレッドではなく、スレッドが解放されたときにスレッドがピックアップするように通知されるタイマーが使用されています。
(I3arnonの答えに基づいて構築)
同期操作とasync-await
を使用する操作が全体的に同じ時間がかかるということは絶対に真実ではありません。
async-await
には、いくつかの追加のロジックが含まれています。完了した待機者と状態マシンのチェックが含まれます。これにより、一部の非同期操作は対応する同期操作よりも時間がかかります。
一方、async-await
に適したほとんどの操作は自然に非同期であり、ルックアンドフィールを同期させるためにいくつかの余分な処理が含まれます。これらの場合、非同期操作は同期操作よりも時間がかかりません。
質問の引用は、Webアプリケーションに関連しています。 Webアプリケーションの場合、非同期操作とは、各リクエストを数マイクロ秒節約することよりも、許容可能な時間内に最大数のリクエストを処理することです。一方、コンテキストの切り替えが含まれる場合は、時間がかかります。そのため、WebアプリケーションでTask.Run
を使用すると、アプリケーションにとって良いことよりも悪いことの方が多くなります。
async-awit
の詳細については、 my async-awit
curation の記事をご覧ください。