第1の方法では、コンパイラはタスクの完了後に "ステートマシン"コードを生成し、return await service.GetAsync();
行に戻します。ラインDoSomething();
がservice.GetAsync
タスクが完了した後にのみ実行されます
public async Task<Something> GetSomethingAsync()
{
var somethingService = new SomethingService();
// Here execution returns to the caller and returned back only when Task is completed.
Something value = await service.GetAsync();
DoSomething();
return value;
}
:以下の例を考えてみましょう。
2番目の方法は、完了を待たずにservice.GetAsync
の実行を開始し、対応するTask
を呼び出し元に返します。だから例のDoSomething()
上記
public Task<Something> GetSomethingAsync()
{
var somethingService = new SomethingService();
Task<Something> valueTask = service.GetAsync();
DoSomething();
return valueTask;
}
は、タスクの完了を待たずに直線Task<Something> valueTask = service.GetAsync();
後に実行されます。
別のスレッドでasync
メソッドを実行する方法自体によって異なります。
メソッドがIO
の操作を実行した場合、別のスレッドはスレッドを無駄にし、何もしません。応答を待つだけです。私の意見ではasync - await
は、IO
操作のための完全なアプローチです。
GetAsync
メソッドがたとえばTask.Run
の場合、スレッドプールからフェッチされた別のスレッドに実行が移ります。以下は
は簡単な例ではなく、良いものですが、それは説明しようとしたロジックを示しています。
static async Task GetAsync()
{
for(int i = 0; i < 10; i++)
{
Console.WriteLine($"Iterate GetAsync: {i}");
await Task.Delay(500);
}
}
static Task GetSomethingAsync() => GetAsync();
static void Main(string[] args)
{
Task gettingSomethingTask = GetSomethingAsync();
Console.WriteLine("GetAsync Task returned");
Console.WriteLine("Start sleeping");
Thread.Sleep(3000);
Console.WriteLine("End sleeping");
Console.WriteLine("Before Task awaiting");
gettingSomethingTask.Wait();
Console.WriteLine("After Task awaited");
Console.ReadLine();
}
、出力は次のようになります。
Iterate GetAsync: 0
GetAsync Task returned
Start sleeping
Iterate GetAsync: 1
Iterate GetAsync: 2
Iterate GetAsync: 3
Iterate GetAsync: 4
Iterate GetAsync: 5
End sleeping
Before Task awaiting
Iterate GetAsync: 6
Iterate GetAsync: 7
Iterate GetAsync: 8
Iterate GetAsync: 9
After Task awaited
をあなたがの実行を見ることができるようにGetAsync
はそれを呼び出した直後に開始します。
はGetSomethingAsync()
場合に変更されます。別のタスク内にラップGetAsync
static Task GetSomethingAsync() => new Task(async() => await GetAsync());
が、その後、GetAsync()
が全く実行されず、出力は次のようになります。もちろん
GetAsync Task returned
Start sleeping
End sleeping
Before Task awaiting
After Task awaited
必要になります行gettingSomethingTask.Wait();
を削除する必要があります。これは、アプリケーションが起動していないタスクを待つためです。
最初のオプションはタスクの完了を待ちますが、2番目のオプションは完了しません。だから二番目の方がはるかに速くなるでしょう。 – Enigmativity
@Enigmativity、両方のメソッドが同時に呼び出し元に戻ります。しかし、2番目の方法では、 "awating"タスクの責任は呼び出し側に移されます。最初のアプローチでは、タスクが終了したときにコードの実行が返されます。 – Fabio
@Enigmativityいいえ、どちらも同じ動作のタスクを返す –