Trước tiên, hãy làm rõ một số thuật ngữ: "không đồng bộ" ( async
) có nghĩa là nó có thể mang lại quyền kiểm soát cho luồng gọi trước khi bắt đầu. Trong một async
phương thức, các điểm "năng suất" đó là các await
biểu thức.
Điều này rất khác so với thuật ngữ "không đồng bộ", vì (mis) được sử dụng bởi tài liệu MSDN trong nhiều năm có nghĩa là "thực thi trên một luồng nền".
Để hiểu thêm về vấn đề này, async
rất khác so với "chờ đợi"; có một số async
phương thức mà kiểu trả về không được chờ đợi và nhiều phương thức trả về kiểu không thể chờ được async
.
Đủ về những gì họ không ; đây là những gì họ đang có :
- Các
async
từ khóa cho phép một phương pháp không đồng bộ (có nghĩa là, nó cho phép await
biểu thức). async
phương thức có thể trả về Task
, Task<T>
hoặc (nếu bạn phải) void
.
- Bất kỳ loại nào theo một mô hình nhất định có thể được chờ đợi. Các loại phổ biến nhất đang chờ đợi là
Task
và Task<T>
.
Vì vậy, nếu chúng tôi định dạng lại câu hỏi của bạn thành "làm thế nào tôi có thể chạy một hoạt động trên một luồng nền theo cách mà nó được chờ đợi", câu trả lời là sử dụng Task.Run
:
private Task<int> DoWorkAsync() // No async because the method does not need await
{
return Task.Run(() =>
{
return 1 + 2;
});
}
(Nhưng mô hình này là một cách tiếp cận kém; xem bên dưới).
Nhưng nếu câu hỏi của bạn là "làm cách nào để tạo một async
phương thức có thể trả lại cho người gọi thay vì chặn", thì câu trả lời là khai báo phương thức async
và sử dụng await
cho các điểm "mang lại" của nó:
private async Task<int> GetWebPageHtmlSizeAsync()
{
var client = new HttpClient();
var html = await client.GetAsync("http://www.example.com/");
return html.Length;
}
Vì vậy, mô hình cơ bản của mọi thứ là có async
mã phụ thuộc vào "awaitables" trong các await
biểu thức của nó . Những "awaitables" này có thể là các async
phương thức khác hoặc chỉ là các phương thức thông thường trả về các awaitables. Phương pháp thông thường trở lại Task
/ Task<T>
có thể sử dụng Task.Run
để thực thi mã trên một sợi nền, hoặc (thường) họ có thể sử dụng TaskCompletionSource<T>
hoặc một trong các phím tắt của nó ( TaskFactory.FromAsync
, Task.FromResult
, vv). Tôi không khuyên bạn nên gói toàn bộ một phương pháp vào Task.Run
; phương pháp đồng bộ phải có chữ ký đồng bộ và nên để lại cho người tiêu dùng xem có nên gói trong Task.Run
:
private int DoWork()
{
return 1 + 2;
}
private void MoreSynchronousProcessing()
{
// Execute it directly (synchronously), since we are also a synchronous method.
var result = DoWork();
...
}
private async Task DoVariousThingsFromTheUIThreadAsync()
{
// I have a bunch of async work to do, and I am executed on the UI thread.
var result = await Task.Run(() => DoWork());
...
}
Tôi có một async
/ await
giới thiệu trên blog của tôi; cuối cùng là một số tài nguyên tiếp theo tốt. Các tài liệu MSDN async
cũng tốt một cách bất thường.