Phương thức của tôi trả về Task
. Tôi muốn đợi cho đến khi nó hoàn thành. Tôi nên sử dụng
.Wait()
hoặc .GetAwaiter().GetResult()
? sự khác biệt giữa chúng là gì?
Phương thức của tôi trả về Task
. Tôi muốn đợi cho đến khi nó hoàn thành. Tôi nên sử dụng
.Wait()
hoặc .GetAwaiter().GetResult()
? sự khác biệt giữa chúng là gì?
Câu trả lời:
Cả hai đều là sự chờ đợi đồng bộ cho kết quả của hoạt động (và bạn nên tránh những điều đó nếu có thể).
Sự khác biệt chủ yếu là trong việc xử lý các trường hợp ngoại lệ. Với Wait
, dấu vết ngăn xếp ngoại lệ không bị thay đổi và đại diện cho ngăn xếp thực tế tại thời điểm ngoại lệ, vì vậy nếu bạn có một đoạn mã chạy trên một chuỗi nhóm luồng, bạn sẽ có một ngăn xếp như
ThreadPoolThread.RunTask
YourCode.SomeWork
Mặt khác, .GetAwaiter().GetResult()
sẽ làm lại dấu vết ngăn xếp để xem xét tất cả ngữ cảnh không đồng bộ, bỏ qua rằng một số phần của mã thực thi trên luồng UI và một số phần trên luồng ThreadPool, và một số chỉ là I / O không đồng bộ. Vì vậy, dấu vết ngăn xếp của bạn sẽ phản ánh một bước giống như đồng bộ thông qua mã của bạn :
TheSyncMethodThatWaitsForTheAsyncMethod
YourCode.SomeAsyncMethod
SomeAsync
YourCode.SomeWork
Điều này có xu hướng làm cho các dấu vết ngăn xếp ngoại lệ hữu ích hơn rất nhiều, ít nhất là. Bạn có thể thấy nơi YourCode.SomeWork
được gọi trong ngữ cảnh ứng dụng của bạn , thay vì "cách thực tế mà ứng dụng được chạy".
Một ví dụ về cách hoạt động của điều này là trong nguồn tham khảo (tất nhiên là không theo hợp đồng).
TaskAwaiter
là chi tiết triển khai. Mặt khác, cơ chế / awaiter awaitable là tài liệu, và sử dụng vịt-gõ - GetAwaiter
là await
như GetEnumerator
là foreach
hoặc Dispose
là using
. Tất cả điều này được định nghĩa trong đặc tả C # bất kể bộ chờ cụ thể đang được sử dụng - lưu ý rằng Task.GetAwaiter
"dành cho việc sử dụng trình biên dịch hơn là để sử dụng trong mã ứng dụng." Nhưng vấn đề là mục đích sử dụng là để làm await
, không phải Wait()
cũng không GetAwaiter().GetResult()
- nhưng GetResult
cung cấp cho bạn những ngăn xếp đẹp hơn nếu bạn cần.