私の理解では、async
そしてawait
目的はコードの書きやすさと読みやすさを向上させることですが、それらを使用することは、長時間実行されるロジックを実行するためにバックグラウンド スレッドを生成することと同じですか?
現在、最も基本的な例を試しています。インラインでコメントをいくつか追加しました。詳しく説明していただけますか?
// I don't understand why this method must be marked as `async`.
private async void button1_Click(object sender, EventArgs e)
{
Task<int> access = DoSomethingAsync();
// task independent stuff here
// this line is reached after the 5 seconds sleep from
// DoSomethingAsync() method. Shouldn't it be reached immediately?
int a = 1;
// from my understanding the waiting should be done here.
int x = await access;
}
async Task<int> DoSomethingAsync()
{
// is this executed on a background thread?
System.Threading.Thread.Sleep(5000);
return 1;
}
ベストアンサー1
を使用するとasync
、await
コンパイラはバックグラウンドでステート マシンを生成します。
ここで、何が起こっているのかを大まかに説明できる例を挙げます。
public async Task MyMethodAsync()
{
Task<int> longRunningTask = LongRunningOperationAsync();
// independent work which doesn't need the result of LongRunningOperationAsync can be done here
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation
{
await Task.Delay(1000); // 1 second delay
return 1;
}
さて、ここで何が起こるでしょうか:
Task<int> longRunningTask = LongRunningOperationAsync();
実行を開始するLongRunningOperation
独立した作業は、メイン スレッド (スレッド ID = 1) に
await longRunningTask
到達すると仮定して実行されます。ここで、 が
longRunningTask
終了しておらず、まだ実行中の場合は、MyMethodAsync()
呼び出しメソッドに戻るため、メイン スレッドはブロックされません。 がlongRunningTask
完了すると、ThreadPool のスレッド (任意のスレッド) がMyMethodAsync()
以前のコンテキストに戻り、実行を続行します (この場合は、結果をコンソールに出力します)。
longRunningTask
2 番目のケースは、 がすでに実行を終了していて、結果が利用できる場合です。 に到達したときにawait longRunningTask
はすでに結果があるため、コードはまったく同じスレッドで実行を続けます。 (この場合は、結果をコンソールに出力します)。 もちろん、 が関係する上記の例では、これは当てはまりませんTask.Delay(1000)
。