正确使用Async / Await的困惑

时间:2016-07-25 11:53:40

标签: c# concurrency async-await

这是我在Windows窗体应用程序中实现的async / await

async Task<int> DoAysnc1()
{
    await Task.Delay(3000);
    return 3000;
}

async Task<int> DoAsync2()
{
    await Task.Delay(5000);
    return 5000;
}

private async void button1_Click(object sender, EventArgs e)
{
    this.textBox1.Text = "";
    var doAsync1 = DoAysnc1();
    var doAsync2 = DoAysnc2();
    var async1 = await doAsync1;
    var async2 = await doAsync2;
    this.textBox1.Text = $"{async1} & {async2}";
}

5秒后,TextBox中的结果为&#34; 3000 & 5000&#34;。

但是当我像这样修改button1_Click时:

private async void button1_Click(object sender, EventArgs e)
{
    this.textBox1.Text = "";
    var async1 = await DoAysnc1();
    var async2 = await DoAysnc2();
    this.textBox1.Text = $"{async1} & {async2}";
}

结果相同,但需要8秒。

为什么第二版button1_Click会同步?

3 个答案:

答案 0 :(得分:5)

以下是差异的解释:

this.textBox1.Text = "";
var doAsync1 = DoAysnc1();         // <--- Run DoAsync1
var doAsync2 = DoAysnc2();         // <--- Run DoAsync2
var async1 = await doAsync1;       // <--- wait for DoAsync1 to finish
var async2 = await doAsync2;       //<--- wait for DoAsync2 to finish
this.textBox1.Text = $"{async1} & {async2}";

虽然:

this.textBox1.Text = "";
var async1 = await DoAysnc1();          // <-- Run DoAsync1 and wait for it to be done
var async2 = await DoAysnc2();          // <-- Run DoAsync2 and wait for it to be done
this.textBox1.Text = $"{async1} & {async2}";

所以在第一个版本中,两个任务都在同一时间运行。在第二个版本中,您从未运行第二个任务,直到第一个任务完成。

我认为阅读Article对你的知识来说将是一个很大的优势。

答案 1 :(得分:4)

通过一些评论可以使实际发生的事情更清楚:

// Starts DoAsync1 asynchronously
var doAsync1 = DoAysnc1();

// Starts DoAsync2 asynchronously
var doAsync2 = DoAysnc2();

// From now on, both task are executing

// Wait for DoAsync1 completion
var async1 = await doAsync1;

// Wait for DoAsync2 completion
var async2 = await doAsync2;

对于第二种情况:

// Starts DoAsync1 asynchronously, and wait for the task completion (3s)
var async1 = await DoAysnc1();

// Starts DoAsync2 asynchronously, and wait for the task completion (5s)
var async2 = await DoAysnc2();

答案 2 :(得分:2)

DoAsync1DoAsync2返回等待的Task个对象。如果你一个接一个地等待它们,那么它们将被一个接一个地执行(首先等待第一个完成,然后等待第二个)。为了并行运行它们,您可以先创建Task - 对象,然后使用Task.WhenAll等待其结果。

private async void button1_Click(object sender, EventArgs e)
{
    this.textBox1.Text = "";

    var task1 = DoAysnc1();
    var task2 = DoAysnc2();
    await Task.WhenAll(task1, task2)

    this.textBox1.Text = $"{task1.Result} & {task2.Result}";
}