1. ホーム
  2. c#

[解決済み] async」と「await」の使い方とタイミング

2022-03-18 07:43:34

質問

私の理解では asyncawait しかし、これらを使用することは、長時間のロジックを実行するためにバックグラウンドスレッドを生成することと同じなのでしょうか?

現在、最も基本的な例を試しているところです。インラインでコメントを追加しています。それを明確にすることができますか?

// 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;
}

解決方法は?

を使用する場合 asyncawait を実行すると、コンパイラはバックグラウンドでステートマシンを生成する。

以下はその例で、高レベルの詳細について説明できると思います。

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;
}

OK、ではここで何が起こるか。

  1. Task<int> longRunningTask = LongRunningOperationAsync(); が実行を開始します。 LongRunningOperation

  2. メインスレッド(スレッドID=1)で独立した作業が行われるとします。 await longRunningTask に到達します。

    ここで、もし longRunningTask が終了しておらず、まだ実行中です。 MyMethodAsync() は呼び出し元のメソッドに戻るので、メインスレッドがブロックされることはありません。そのため、メインスレッドがブロックされることはありません。 longRunningTask が終了すると、ThreadPool からのスレッド (任意のスレッドで可) が MyMethodAsync() を以前のコンテキストで実行し、実行を継続します (この場合、コンソールに結果を出力します)。

2つ目のケースは longRunningTask はすでに実行を終了しており、結果が利用可能です。に到達すると await longRunningTask そのため、コードはまったく同じスレッドで実行され続けます。(この場合、結果はコンソールに出力されます)。もちろん、これは上記の例には当てはまりません。 Task.Delay(1000) が関わってきます。