Bạn nhận được lỗi đó vì Task
lớp đã bắt đầu nhiệm vụ trước khi giao nó cho bạn. Bạn chỉ nên gọi Start
một tác vụ mà bạn tạo bằng cách gọi hàm khởi tạo của nó, và bạn thậm chí không nên làm điều đó trừ khi bạn có lý do thuyết phục để không bắt đầu tác vụ khi bạn tạo nó; nếu bạn muốn nó bắt đầu ngay lập tức, bạn nên sử dụng Task.Run
hoặc Task.Factory.StartNew
để tạo và bắt đầu một cái mới Task
.
Vì vậy, bây giờ chúng ta biết cách loại bỏ sự phiền phức đó Start
. Bạn sẽ chạy mã của mình và thấy rằng hộp thông báo được hiển thị ngay lập tức, không phải 5 giây sau, có chuyện gì vậy?
Chà, Task.Delay
chỉ giao cho bạn một nhiệm vụ sẽ hoàn thành sau 5 giây. Nó không ngừng thực hiện chuỗi trong 5 giây. Những gì bạn muốn làm là có một số mã được thực thi sau khi tác vụ đó kết thúc. Đó là những gì ContinueWith
dành cho. Nó cho phép bạn chạy một số mã sau khi hoàn thành một nhiệm vụ cụ thể:
public void FunctionA()
{
Task.Delay(5000)
.ContinueWith(t =>
{
MessageBox.Show("Waiting Complete");
});
}
Điều này sẽ hoạt động như mong đợi.
Chúng tôi cũng có thể tận dụng await
từ khóa của C # 5.0 để thêm các đoạn liên tục dễ dàng hơn:
public async Task FunctionA()
{
await Task.Delay(5000);
MessageBox.Show("Waiting Complete");
}
Trong khi lời giải thích đầy đủ về những gì đang xảy ra ở đây nằm ngoài phạm vi của câu hỏi này, kết quả cuối cùng là một phương thức hoạt động rất giống với phương pháp trước đó; nó sẽ hiển thị một hộp thông báo 5 giây sau khi bạn gọi phương thức, nhưng bản thân phương thức sẽ trả về [gần như] ngay lập tức trong cả hai trường hợp. Điều đó nói rằng, await
nó rất mạnh mẽ và cho phép chúng ta viết các phương thức có vẻ đơn giản và dễ hiểu, nhưng điều đó sẽ khó hơn và lộn xộn hơn nhiều nếu sử dụng ContinueWith
trực tiếp. Nó cũng giúp đơn giản hóa rất nhiều việc xử lý lỗi, lấy ra rất nhiều mã soạn sẵn.
Wait()
một tác vụ sẽ chặn luồng hiện tại cho đến khi tác vụ được giải quyết. Đó gần như không bao giờ là điều bạn muốn xảy ra.