等待声明与表达

时间:2012-09-19 21:08:26

标签: c# async-await

我正在关注MSDN上的await教程,我正在尝试找出使用await作为语句与使用{{1}之间的区别作为表达式。整个异步等待的事情让我大吃一惊,我找不到这个特例的任何例子。

基本上,我想看看如何异步使用多个await,这意味着我不想在第二个开始之前等待第一个完成。对我来说,这一开始就违背了异步的目的:

await

但是,通过微妙的更改,两个“完成”的总计只需要3秒钟,这就是我想要的 - 两个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"; } 真正异步运行:

await

我的问题是,为什么这些行为有所不同?我在这里错过了什么微妙的一点?

2 个答案:

答案 0 :(得分:11)

首先,您需要区分 parallelism asynchrony 。在第一种情况下,它可能仍然值得同步执行操作(实际上第二个操作可能取决于第一个操作的结果)以释放UI线程等。

但至于为什么他们的行为不同 - await 只是一个表达式。它是一种可以作为语句出现的表达式,但它的行为方式相同,就像调用返回字符串的方法一样,但忽略了返回值。您可以通过将第一个代码更改为:

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

var b = WaitAsynchronouslyAsync();
await b;

那还需要6秒钟。关键是你只是在等待第一个完成后才开始第二个异步操作。在第二个示例中,两个异步操作同时发生。

您仍然可以将值分配给变量,您只需要记住等待:

// 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有关。

答案 1 :(得分:4)

在这两种情况下,await关键字都会引入异步。您看到差异的原因是,在案例1中,您按顺序启动两个任务,在案例2中,您让它们并行运行。

也许对这两种情况的逐步解释清除了事情

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

这里发生的是:

  • 任务(a)启动
  • 等待任务a(控制权返回给调用者)
  • 当任务a在3秒后结束时,该方法恢复;任务(b)开始
  • 等待任务b(控制权返回给调用者)
  • 当任务b在另外3秒后完成时,文本出现

在第二种情况下:

var a = WaitAsynchronouslyAsync();     
var b = WaitAsynchronouslyAsync();     
await a;     
await b;     
  • 任务(a)启动
  • 任务(b)已启动
  • 任务(a)'等待'(即控制权返回给主叫方)
  • 当任务(a)在3秒后完成时,等待任务(b)
  • 因为任务b大约在3秒前启动,所以它与(a)
  • 同时或多或少地完成
  • 文字显示