2012-09-19 45 views
5

tôi sau await hướng dẫn trên MSDN, và tôi đang cố gắng tìm ra sự khác biệt giữa việc sử dụng await như một tuyên bố so với sử dụng await như là một biểu . Toàn bộ điều không mong đợi này đang uốn cong tâm trí của tôi và tôi không thể tìm thấy bất kỳ ví dụ nào cho trường hợp cụ thể này.đang chờ đợi tuyên bố vs biểu

Về cơ bản, tôi muốn xem cách sử dụng nhiều await s một cách không đồng bộ, có nghĩa là tôi không muốn phải chờ cho người đầu tiên hoàn thành trước khi lần thứ hai bắt đầu. Này, với tôi, đánh bại mục đích của sự không đồng bộ để bắt đầu với:

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

Tuy nhiên, với một sự thay đổi tinh tế nó chỉ mất 3 giây tổng cho hai "Finished" s xuất hiện, đó là những gì tôi muốn - hai số await s chạy thực sự không đồng bộ:

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

Câu hỏi của tôi là, tại sao các hành vi này khác? Tôi đang thiếu điểm tinh tế nào ở đây?

Trả lời

11

Trước tiên, bạn cần phải phân biệt giữa song songkhông đồng bộ. Trong trường hợp đầu tiên, nó có thể dễ dàng vẫn có giá trị thực hiện các hoạt động đồng bộ (và thực sự là hoạt động thứ hai có thể phụ thuộc vào kết quả đầu tiên) để giải phóng các chủ đề giao diện người dùng, v.v.

Nhưng về lý do tại sao chúng hoạt động khác - awaitchỉ một biểu thức. Đó là loại biểu thức có thể xuất hiện như một câu lệnh, nhưng nó sẽ hoạt động theo cùng một cách, giống như gọi một phương thức trả về một chuỗi, nhưng bỏ qua giá trị trả lại. Bạn có thể thấy điều đó bằng cách thay đổi mã đầu tiên của mình thành:

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

var b = WaitAsynchronouslyAsync(); 
await b; 

Điều đó sẽ vẫn mất 6 giây. Vấn đề là bạn chỉ bắt đầu hoạt động không đồng bộ thứ hai sau mà bạn đã chờ kết thúc đầu tiên. Trong ví dụ thứ hai của bạn, cả hai hoạt động không đồng bộ xảy ra cùng một lúc.

Bạn vẫn có thể làm điều đó gán giá trị cho một biến, bạn chỉ cần nhớ awaitables:

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

Vì vậy, về cơ bản, sự khác biệt không phải là để làm với tuyên bố/biểu hiện - đó là liên quan đến việc chuỗi có bắt đầu/chờ/bắt đầu/đang chờ hay bắt đầu/bắt đầu/đang chờ/chờ đợi hay không.

+0

Chỉnh sửa cuối cùng của bạn đã khiến tôi nhận ra, cảm ơn - giải trình tự là vấn đề. Tôi nên nhận ra rằng cả hai đều là biểu cảm. –

4

Trong cả hai trường hợp, từ khóa chờ đợi giới thiệu không đồng bộ. Lý do bạn thấy sự khác biệt là trong trường hợp 1 bạn bắt đầu cả hai nhiệm vụ tuần tự, trong trường hợp 2 bạn cho phép chúng chạy song song.

Có lẽ từng bước giải thích của cả hai tình huống xóa mọi thứ lên

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

gì xảy ra ở đây là:

  • một nhiệm vụ (a) được bắt đầu
  • nhiệm vụ một là chờ đợi (điều khiển được trả lại cho người gọi)
  • khi công việc hoàn tất sau 3 giây, phương thức sẽ tiếp tục; nhiệm vụ (b) được bắt đầu
  • nhiệm vụ b được chờ đợi (kiểm soát được trả lại cho người gọi)
  • khi nhiệm vụ b xong cái khác 3 giây, văn bản xuất hiện

Trong trường hợp thứ hai:

var a = WaitAsynchronouslyAsync();  
var b = WaitAsynchronouslyAsync();  
await a;  
await b;  
  • nhiệm vụ (a) được bắt đầu
  • nhiệm vụ (b) được bắt đầu
  • nhiệm vụ (a) là 'aw aited '(tức là điều khiển được trả lại cho người gọi)
  • khi công việc (a) kết thúc sau 3 giây, nhiệm vụ (b) được chờ đợi
  • vì nhiệm vụ b được bắt đầu khoảng 3 giây trước đây cùng lúc với (a)
  • văn bản xuất hiện