2013-06-29 20 views
8

Vì vậy, tôi đã hỏi this question về async, và tôi nghĩ rằng nó nó chỉ là một cú pháp đường cho:C# 5 async như một cú pháp đường (hay không)?

Task<..>...ContinueWith...

Và cuối cùng kiểm tra việc Result tài sản.

Tôi thậm chí còn hỏi một câu hỏi về nó here và tôi đã nói:

enter image description here

enter image description here

Nhưng Hôm nay I was corrected by Jon Skeet

"Đó là một chặng đường rất dài từ đó".

Vậy sự khác biệt chính giữa 2 cách tiếp cận này là gì?

+3

* Về mặt khái niệm * việc sử dụng 'await' tương tự như' ContinueWith', nhưng có rất nhiều chi tiết nhỏ mà 'await' đảm nhiệm cho bạn rằng bạn phải tự làm với' ContinueWith'. –

+0

Bạn cắt câu trả lời thật thanh lịch như thế nào? :) –

+0

@YairNevet cái nào? –

Trả lời

15

thêm tiếp tục - nhưng tự xây dựng việc tiếp tục đó có thể rất đau đớn, do cần phải mang theo tất cả thông tin về nơi chúng tôi đến và trạng thái địa phương.

Như một ví dụ rất đơn giản, tôi đề nghị bạn cố gắng để đưa ra tương đương với phương pháp async này:

public static async Task<int> SumTwoOperationsAsync() 
{ 
    var firstTask = GetOperationOneAsync(); 
    var secondTask = GetOperationTwoAsync(); 
    return await firstTask + await secondTask; 
} 

// These are just examples - you don't need to translate them. 
private async Task<int> GetOperationOneAsync() 
{ 
    await Task.Delay(500); // Just to simulate an operation taking time 
    return 10; 
} 

private async Task<int> GetOperationTwoAsync() 
{ 
    await Task.Delay(100); // Just to simulate an operation taking time 
    return 5; 
} 

Thật cố gắng đưa ra tương đương với phương pháp đầu tiên. Tôi nghĩ rằng bạn sẽ tìm thấy nó mất khá nhiều mã - đặc biệt là nếu bạn thực sự muốn quay trở lại một chủ đề thích hợp mỗi lần. (Hãy tưởng tượng mã trong phương thức async đó cũng đã sửa đổi giao diện người dùng WPF chẳng hạn.) Ồ, và đảm bảo rằng nếu một trong các tác vụ thất bại, tác vụ trả về của bạn cũng không thành công. (Các phương pháp async sẽ thực sự "bỏ lỡ" sự thất bại của nhiệm vụ thứ hai nếu nhiệm vụ đầu tiên cũng thất bại, nhưng đó là một vấn đề tương đối nhỏ IMO.)

Tiếp theo, tìm hiểu cách bạn cần thay đổi mã của bạn nếu bạn cần tương đương với try/finally theo phương pháp async. Một lần nữa, điều đó sẽ làm cho phương thức không async phức tạp hơn. Tất cả có thể được thực hiện, nhưng đó là một cơn đau ở cổ.

Vì vậy, có, đó là "chỉ" cú pháp đường. Vì vậy, là foreach. Vì vậy, là một vòng lặp for (hoặc bất kỳ loại vòng lặp nào khác). Trong trường hợp của async/await, đó là đường cú pháp có thể thực sự thay đổi rất nhiều mã của bạn.

nhiều các video và bài đăng trên blog xung quanh async, và tôi hy vọng rằng chỉ xem/đọc một vài trong số họ sẽ cung cấp cho bạn đủ sáng suốt để hiểu rằng điều này là xa một tinh chỉnh nhỏ: nó triệt thay đổi cách thực tế là viết một lượng lớn mã không đồng bộ một cách chính xác.

Ngoài ra, dựa trên mẫu, không đồng bộ/chờ đợi không chỉ hoạt động trên Task/Task<T>. Bạn có thể chờ đợi bất cứ điều gì mà tuân thủ các mô hình awaitable.Trong thực tế, rất ít nhà phát triển sẽ cần phải triển khai thực hiện mẫu đó, nhưng nó cho phép các phương thức như Task.Yield trả về một YieldAwaitable thay vì một nhiệm vụ.

+0

-Cảm ơn bạn Jon. –

+0

Vì vậy, không, nó không phải là "chỉ" cú pháp đường! Xem để quản lý IL. Bạn sẽ rất ngạc nhiên trước sự khác biệt giữa Task có và không sử dụng async/await. – hVostt

+2

@hVostt: Tôi đã giải mã * rất nhiều * mã async/await. Tôi sẽ không ngạc nhiên trước sự khác biệt nữa, nhưng tôi vẫn nghĩ đó là "chỉ" cú pháp. Đó là đường cú pháp rất hữu ích và khá phức tạp, và đôi khi kết quả là mã không thể được biểu diễn bằng * chính xác * IL sử dụng C# 4 - nhưng về cơ bản nó không làm bất cứ điều gì thực sự không thể thực hiện được trước đây. Nó không giống như generics, đó là một sự thay đổi cơ bản trong hệ thống kiểu. Đây chỉ là trình biên dịch thông minh. Tôi không cố gắng đánh giá thấp mức độ hữu ích của nó - tôi * yêu * không đồng bộ. Nhưng nó vẫn là cú pháp đường IMO. –

Các vấn đề liên quan