Chỉ cần có VS2012 và cố gắng xử lý async
.
Giả sử tôi đã có một phương pháp lấy một số giá trị từ một nguồn chặn. Tôi không muốn người gọi phương thức chặn. Tôi có thể viết phương thức để thực hiện một cuộc gọi lại được gọi khi giá trị đến, nhưng vì tôi đang sử dụng C # 5, tôi quyết định làm cho phương thức không đồng bộ để người gọi không phải xử lý các cuộc gọi lại:
// contrived example (edited in response to Servy's comment)
public static Task<string> PromptForStringAsync(string prompt)
{
return Task.Factory.StartNew(() => {
Console.Write(prompt);
return Console.ReadLine();
});
}
Đây là một phương pháp ví dụ gọi nó. Nếu PromptForStringAsync
không đồng bộ, phương thức này sẽ yêu cầu lồng lại một cuộc gọi lại trong một cuộc gọi lại. Với async, tôi có thể viết phương thức của mình theo cách rất tự nhiên này:
public static async Task GetNameAsync()
{
string firstname = await PromptForStringAsync("Enter your first name: ");
Console.WriteLine("Welcome {0}.", firstname);
string lastname = await PromptForStringAsync("Enter your last name: ");
Console.WriteLine("Name saved as '{0} {1}'.", firstname, lastname);
}
Càng xa càng tốt. Vấn đề là khi tôi gọi GetNameAsync:
public static void DoStuff()
{
GetNameAsync();
MainWorkOfApplicationIDontWantBlocked();
}
Toàn bộ vấn đề GetNameAsync
là nó không đồng bộ. Tôi không muốn chặn nó, vì tôi muốn quay lại MainWorkOfApplicationIDontWantBlocked ASAP và để GetNameAsync thực hiện công việc của mình trong nền. Tuy nhiên, gọi nó theo cách này cung cấp cho tôi một cảnh báo trình biên dịch trên GetNameAsync
dòng:
Warning 1 Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
Tôi hoàn toàn biết rằng "việc thực hiện phương thức hiện tại vẫn tiếp tục trước khi cuộc gọi kết thúc". Đó là điểm của mã không đồng bộ, phải không?
Tôi thích mã của mình để biên dịch mà không có cảnh báo, nhưng không có gì để "sửa" ở đây vì mã đang làm chính xác những gì tôi dự định làm. Tôi có thể thoát khỏi cảnh báo bằng cách lưu trữ giá trị trả về của GetNameAsync
:
public static void DoStuff()
{
var result = GetNameAsync(); // supress warning
MainWorkOfApplicationIDontWantBlocked();
}
Nhưng bây giờ tôi có mã thừa. Visual Studio dường như hiểu rằng tôi đã buộc phải viết mã không cần thiết này, bởi vì nó ngăn chặn cảnh báo "giá trị không bao giờ được sử dụng" thông thường.
Tôi cũng có thể loại bỏ cảnh báo bằng cách gói GetNameAsync theo phương thức không đồng bộ:
public static Task GetNameWrapper()
{
return GetNameAsync();
}
Nhưng điều đó thậm chí còn nhiều hơn nữa đang dư thừa. Vì vậy, tôi phải viết mã tôi không cần hoặc chịu đựng một cảnh báo không cần thiết.
Có điều gì đó về việc tôi sử dụng async không đúng ở đây?
GetNameAsync
cung cấp tên đầy đủ mà được cung cấp bởi người sử dụng (ví dụ Task<Name>
, thay vì chỉ trả lại một Task
? DoStuff
Sau đó có thể lưu trữ công việc đó, và một trong hai await
nó sau khi các phương pháp khác, hoặc thậm chí vượt qua nhiệm vụ mà khác phương pháp để nó có thể await
hoặc Wait
nó ở đâu đó bên trong triển khai.
async
từ khóa.
PromptForStringAsync
bạn làm nhiều việc hơn bạn cần; Chỉ cần trả lại kết quả củaTask.Factory.StartNew
. Đó là một nhiệm vụ mà giá trị của người đó là chuỗi được nhập trong bàn điều khiển. Không cần phải chờ đợi kết quả trả về; làm như vậy không thêm giá trị mới.