2012-09-19 47 views
5

我下面的MSDN上await教程中,我試圖找出使用await作爲聲明與使用await作爲表達之間的差異。這整個異步等待的事情正在彎曲我的頭腦,我無法找到這個特定案例的任何例子。等待陳述與表達

基本上,我想看看如何異步使用多個await,這意味着我不想在第二個開始之前等待第一個完成。這對我來說,擊敗異步的目的與開始:

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

然而,只需要3秒共有兩個「完成」 S出現,這是我想要什麼微妙的變化 - 兩個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; 
} 

我的問題是,爲什麼這些不同的表現?我在這裏錯過了什麼微妙的點?

回答

11

首先,您需要區分並行性異步。在第一種情況下,它可能仍然值得同步執行操作(事實上第二個操作可能取決於第一個的結果),以釋放UI線程等。

但至於它們爲什麼表現不同 - await只有表達。這種表達方式可以作爲一個語句出現,但它的行爲方式也是一樣,就像調用一個返回字符串的方法,但忽略返回值一樣。您可以看到,通過將您的第一個代碼更改爲:

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

var b = WaitAsynchronouslyAsync(); 
await b; 

這仍然需要6秒鐘。重點在於你只在之後開始第二個異步操作,你等待第一個完成。在第二個例子中,兩個異步操作同時發生。

,您仍然可以做到這一點賦值給一個變量,你只需要記住awaitables:

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

所以基本上,不同的是沒有用的語句/表達做 - 這是與序列是否是開始/等待/開始/等待或開始/開始/等待/等待有關。

+0

您上次的編輯讓我意識到,謝謝 - 排序是問題所在。我應該意識到他們都是表達。 –

4

在這兩種情況下,await關鍵字都引入了異步。你看到區別的原因是,在情況1中,你順序地開始了兩個任務,在情況2中你讓它們並行運行。

也許一步步的這兩種情況下一步的解釋清除的東西了

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

這裏發生的是:

  • (一)啓動
  • 任務一個任務等待(控制被返回給主叫方)
  • 當任務a在3秒後完成時,該方法恢復;任務(b)的開始
  • 任務b等待(控制被返回給調用者)
  • 當任務b的另一個在3秒後完成,文本顯示

在第二種情況:

var a = WaitAsynchronouslyAsync();  
var b = WaitAsynchronouslyAsync();  
await a;  
await b;  
  • 任務(一)啓動
  • 任務(二)啓動
  • 任務(一)爲「AW (即控制返回給調用者)
  • 當任務(a)在3秒鐘後完成時,任務(b)正在等待
  • 由於任務b大約在3秒前啓動,所以完成了或多或少(a)
  • 出現的文字