5

私はMSDNのawaitawaitチュートリアルに従っており、ステートメントとして使用することとawaitとして使用することの違いを理解しようとしています。この非同期待機のすべてが私の心を曲げており、この特定のケースの例を見つけることができません。

基本的に、複数のsを非同期で使用する方法を確認したかったawaitのです。つまり、最初のsが完了するのを待ってから、2番目のsを開始する必要はありません。これは、私にとって、非同期の目的を最初から無効にします。

private async void button1_Click(object sender, EventArgs e)
{
    // Using await as an expression
    string result_a = await WaitAsynchronouslyAsync();
    string result_b = await WaitAsynchronouslyAsync();

    // This takes six seconds to appear
    textBox1.Text = result_a + Environment.NewLine;
    textBox1.Text += result_b;
}

public async Task<string> WaitAsynchronouslyAsync()
{
    await Task.Delay(3000);
    return "Finished";
}

ただし、微妙な変更を加えると、2つの「Finished」が表示されるまでに合計3秒しかかかりません。これは、私が望んでいることです。2つはawait本当に非同期で実行されます。

private async void button1_Click(object sender, EventArgs e)
{
    var a = WaitAsynchronouslyAsync();
    var b = WaitAsynchronouslyAsync();

    // Using await as a statement
    await a;
    await b;

    // This takes three seconds to appear
    textBox1.Text = a.Result + Environment.NewLine;
    textBox1.Text += b.Result;
}

私の質問は、なぜこれらは異なる動作をするのですか?ここで私が見逃している微妙な点は何ですか?

4

2 に答える 2

11

まず、並列処理非同期を区別する必要があります。最初のケースでは、UIスレッドなどを解放するために、操作を同期的に実行する価値があります(実際、2番目の操作は最初の操作の結果に依存する場合があります)。

しかし、なぜそれらが異なって振る舞うのかについてawaitは、単なる表現です。これはステートメントとして表示できる種類の式ですが、文字列を返すメソッドを呼び出すのと同じように動作しますが、戻り値は無視されます。最初のコードを次のように変更すると、それを確認できます。

// Still takes 6 seconds...
var a = WaitAsynchronouslyAsync();
await a;

var b = WaitAsynchronouslyAsync();
await b;

それでも6秒かかります。重要なのは、最初の非同期操作が終了するのを待ったでのみ、2番目の非同期操作を開始するということです。2番目の例では、両方の非同期操作が同時に発生します。

それでもそれを実行して値を変数に割り当てることができます。待機可能な値を覚えておく必要があります。

// This will only take 3 seconds
var a = WaitAsynchronouslyAsync();
var b = WaitAsynchronouslyAsync();
string result_a = await a;
string result_b = await b;

つまり、基本的に、違いはステートメント/式とは関係ありません。シーケンスがstart / await / start/awaitまたはstart/start / await/awaitのどちらであるかと関係があります。

于 2012-09-19T21:12:23.740 に答える
4

どちらの状況でも、awaitキーワードは非同期を導入します。違いが見られる理由は、ケース1では両方のタスクを順番に開始し、ケース2ではそれらを並行して実行させるためです。

たぶん、両方の状況の段階的な説明は物事をクリアします

string result_a = await WaitAsynchronouslyAsync(); 
string result_b = await WaitAsynchronouslyAsync(); 

ここで何が起こるかです:

  • タスク(a)が開始されます
  • タスクaが待機しています(制御が呼び出し元に返されます)
  • タスクaが3秒後に終了すると、メソッドが再開されます。タスク(b)が開始されます
  • タスクbが待機しています(制御が呼び出し元に返されます)
  • さらに3秒後にタスクbが終了すると、テキストが表示されます

2番目の場合:

var a = WaitAsynchronouslyAsync();     
var b = WaitAsynchronouslyAsync();     
await a;     
await b;     
  • タスク(a)が開始されます
  • タスク(b)が開始されます
  • タスク(a)は「待機中」です(つまり、制御が呼び出し元に返されます)
  • タスク(a)が3秒後に終了すると、タスク(b)が待機します
  • タスクbは約3秒前に開始されたため、(a)と同時にほぼ同時に終了します。
  • テキストが表示されます
于 2012-09-19T21:20:26.317 に答える