2011-12-09 20 views
8

Có xấu khi có mã đắt tiền khi bắt đầu một phương thức không đồng bộ, trước khi gọi await đầu tiên? Mã này có nên được bọc với một số TaskEx.Run thay thế không?Có thể các phương thức async có mã đắt tiền trước khi 'chờ đợi' đầu tiên không?

public async Task Foo() 
{ 
    // Do some initial expensive stuff. 
    // ... 

    // First call to an async method with await. 
    await DoSomethingAsync; 
} 
+0

Bạn có thể giả mã một ví dụ không? – vcsjones

Trả lời

10

Như Reed nói, điều đó thực sự phụ thuộc vào ngữ cảnh. Mã phải chạy ở số một số điểm - nhưng tùy thuộc vào ngữ cảnh, mã có thể kết thúc chạy trên một chuỗi chủ đề thay vì một số chủ đề quan trọng.

Thay vì sử dụng Task.Run, tôi muốn sử dụng TaskEx.Yield:

public async Task Foo() 
{ 
    await TaskEx.Yield(); 
    // Do expensive stuff 
} 

Theo như tôi biết, đó là về cơ bản một cách ngay lập tức quay trở lại cho người gọi, nhưng cho phép các phần còn lại của phương pháp async để được lên lịch ngay lập tức. Nếu bạn đang ở trong một cái gì đó giống như một giao diện người dùng Windows Forms, không có điểm trong việc này vì bạn sẽ trở lại giao diện người dùng (và chạy mã đắt tiền ở đó) ngay lập tức - nhưng nó sẽ có ý nghĩa nếu bạn đang ở trong một ngữ cảnh nơi mà các thread hiện tại không nên bị chặn, nhưng tiếp tục được chạy trên thread khác.

5

Không nhất thiết là xấu, nhưng có thể có hậu quả không mong muốn. Nếu người gọi hy vọng rằng mã sẽ hoạt động hoàn toàn không đồng bộ, mã đắt tiền sẽ chạy đồng bộ. Điều này sẽ làm cho nó hoạt động một phần giống như một phương thức đồng bộ, nhưng cũng không đồng bộ, là loại tồi tệ nhất của cả hai thế giới (sự phức tạp thêm từ sự không đồng bộ mà không có sự lặp lại ...)

Nếu có thể, tôi khuyên bạn nên cố gắng có ít mã "đắt tiền" dẫn đến sự chờ đợi đầu tiên. Sử dụng Task.Run (hoặc TaskEx.Run trong CTP) để bọc mã đắt tiền hoặc di chuyển mã đắt tiền vào phương thức không đồng bộ của chính nó (khi đó bạn có thể await) sẽ có lợi trong trường hợp này.

Các vấn đề liên quan