Điều gì sẽ là lựa chọn tốt nhất cho từ khóa chờ đợi trong .NET 4.0? Tôi có một phương thức cần trả về một giá trị sau một phép toán không đồng bộ. Tôi nhận thấy phương thức wait() khóa hoàn toàn luồng, do đó làm cho hoạt động không đồng bộ vô dụng. Các tùy chọn của tôi để chạy hoạt động async trong khi vẫn giải phóng luồng giao diện người dùng là gì?Đang chờ thay thế trong .NET 4.0?
Trả lời
Tôi nghĩ tùy chọn cơ bản của bạn là
- Sử dụng
Task
và.ContinueWith()
- Sử dụng Async CTP và
async
/await
- Sử dụng Reactive Extensions
Cách đơn giản nhất có lẽ là để cài đặt Async CTP. Theo như tôi biết giấy phép cho phép sử dụng comercial. Nó vá các trình biên dịch và đi kèm với một dll 150kb mà bạn có thể đưa vào dự án của bạn.
Bạn có thể sử dụng Task
và .ContinueWith()
. Nhưng điều đó có nghĩa, rằng bạn phải mất một số nỗ lực với xử lý exeption và kiểm soát dòng chảy.
Nhiệm vụ là cấu trúc chức năng. Đó là lý do tại sao ContinueWith()
không trộn lẫn với các cấu trúc bắt buộc như các vòng for
hoặc try-catch
khối. Do đó, async
và await
được giới thiệu để trình biên dịch có thể giúp chúng tôi.
Nếu bạn không thể có sự hỗ trợ của trình biên dịch (tức là bạn sử dụng .Net 4.0), đặt cược tốt nhất của bạn là sử dụng TAP cùng với một khung chức năng. Reactive Extensions là một khuôn khổ rất tốt để điều trị các phương pháp không đồng bộ.
Chỉ cần google cho "nhiệm vụ tiện ích phản hồi" để bắt đầu.
Bạn có thể thực hiện một hành vi như await
với tiêu chuẩn yield
coroutines, tôi đang sử dụng mã này trong mã không phải 4.5. Bạn cần một lớp YieldInstruction
được lấy ra từ phương pháp mà nên chạy async:
public abstract class YieldInstruction
{
public abstract Boolean IsFinished();
}
Sau đó, bạn cần một số hiện thực của YieldInstruction
(ae TaskCoroutine
mà xử lý một nhiệm vụ) và sử dụng nó theo cách này (Pseudo code):
public IEnumerator<YieldInstruction> DoAsync()
{
HttpClient client = ....;
String result;
yield return new TaskCoroutine(() => { result = client.DownloadAsync(); });
// Process result here
}
Bây giờ bạn cần một bộ lập lịch xử lý việc thực hiện các hướng dẫn.
for (Coroutine item in coroutines)
{
if (item.CurrentInstruction.IsFinished())
{
// Move to the next instruction and check if coroutine has been finished
if (item.MoveNext()) Remove(item);
}
}
Khi phát triển WPF hoặc WinForms ứng dụng mà bạn cũng có thể để tránh bất kỳ Invoke
cuộc gọi nếu bạn đang cập nhật coroutines vào đúng thời điểm. Bạn cũng có thể mở rộng ý tưởng để làm cho cuộc sống của bạn dễ dàng hơn. Ví dụ:
public IEnumerator<YieldInstruction> DoAsync()
{
HttpClient client = ....;
client.DownloadAsync(..);
String result;
while (client.IsDownloading)
{
// Update the progress bar
progressBar.Value = client.Progress;
// Wait one update
yield return YieldInstruction.WaitOneUpdate;
}
// Process result here
}
sử dụng đang chờ, nhưng theo đúng cách tôi đoán. Bạn có một số mã? – lboshuizen
Có thể chấp nhận sử dụng VS2012 với C# 5.0 trong khi nhắm mục tiêu .net 4.0 không? Xem [Sử dụng async-await on .net 4] (http://stackoverflow.com/questions/9110472/using-async-await-on-net-4) – CodesInChaos
@CodesInChaos Dành cho đồng nghiệp, không :). – Dante