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 asyncphương thức, các điểm "năng suất" đó là các awaitbiể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, asyncrất khác so với "chờ đợi"; có một số asyncphươ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
asynctừ khóa cho phép một phương pháp không đồng bộ (có nghĩa là, nó cho phép awaitbiểu thức). asyncphươ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à
Taskvà 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 asyncphươ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 asyncvà sử dụng awaitcho 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ó asyncmã phụ thuộc vào "awaitables" trong các awaitbiểu thức của nó . Những "awaitables" này có thể là các asyncphươ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/ awaitgiớ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 asynccũng tốt một cách bất thường.