2013-07-26 24 views
28

Khi kết thúc phương thức không đồng bộ hóa Trả về tác vụ, nếu tôi gọi một phương thức không đồng bộ khác, tôi có thể await hoặc return nhiệm vụ của nó. Đó là hậu quả của mỗi người?Khi kết thúc một phương thức không đồng bộ, tôi có nên quay lại hoặc chờ đợi không?

Task FooAsync() 
    { 
     return BazAsync(); // Option A 
    } 

    async Task BarAsync() 
    { 
     await BazAsync(); // Option B 
    } 
+2

Việc này có thể nguy hiểm nếu bạn kết hợp nó bằng 'using':' using (something) {return BazAsync(); } 'và' sử dụng (cái gì đó) {await BazAsync(); } 'hành xử rất khác nhau. – svick

+0

Liên kết một câu hỏi tương tự: http://stackoverflow.com/q/21033150/1768303 – Noseratio

+2

Tôi đã viết một bài đăng trên blog về [lợi thế và cạm bẫy của eliding 'async'/'await'] (http: //blog.stephencleary. com/2016/12/eliding-async-await.html). –

Trả lời

29

Bạn không thể trả lại nhiệm vụ nếu phương pháp tự nó được tuyên bố là async - vì vậy đây sẽ không làm việc, ví dụ :

async Task BarAsync() 
{ 
    return BazAsync(); // Invalid! 
} 

Điều đó sẽ yêu cầu loại trả lại là Task<Task>.

Nếu phương pháp của bạn là chỉ làm một số lượng nhỏ của công việc và sau đó gọi chỉ một phương pháp async, sau đó lựa chọn đầu tiên của bạn là tốt, và có nghĩa là có một nhiệm vụ ít có liên quan. Bạn nên lưu ý rằng bất kỳ ngoại lệ nào được ném trong phương thức đồng bộ của bạn sẽ được gửi đồng bộ mặc dù - thực sự, đây là cách tôi muốn xử lý xác thực đối số.

Đó cũng là một mô hình phổ biến để triển khai quá tải, ví dụ: bằng mã thông báo hủy.

Chỉ cần lưu ý rằng nếu bạn cần thay đổi để chờ đợi một thứ khác, bạn sẽ cần phải biến nó thành một phương thức async thay thế. Ví dụ:

// Version 1: 
Task BarAsync() 
{ 
    // No need to gronkle yet... 
    return BazAsync(); 
} 

// Oops, for version 2 I need to do some more work... 
async Task BarAsync() 
{ 
    int gronkle = await GronkleAsync(); 
    // Do something with gronkle 

    // Now we have to await BazAsync as we're now in an async method 
    await BazAsync(); 
} 
+2

'Nếu phương pháp của bạn chỉ làm một lượng nhỏ công việc và sau đó chỉ gọi một phương thức không đồng bộ' Trong cụ thể, đây là một mẫu chung cho quá tải các phương thức 'async' (ví dụ:' BarAsync() 'và' BarAsync (CancellationToken) '). –

+1

@StephenCleary: Thật vậy - và tương tự như vậy xác thực đồng bộ theo sau bằng cách trả lại tác vụ async "thực". Sẽ chỉnh sửa để chỉ ra điều đó. –

+0

@JonSkeet, xin lỗi vì đã khôi phục lại điều này sau 3 năm, nhưng câu hỏi - bất cứ khi nào tôi thấy mã không có 'đang chờ' và chỉ trả về 'Tác vụ', nếu có ngoại lệ trong nhiệm vụ đó đôi khi có vẻ như 'biến mất ', ngay cả khi người gọi đang chờ nhiệm vụ. Điều này có liên quan đến nhận xét của bạn về các trường hợp ngoại lệ được ném đồng bộ không? – Cody

1

Kiểm tra liên kết này, nơi nó được mô tả: http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx

async Task<int> TaskOfTResult_MethodAsync() 
{ 
    int hours; 
    // . . . 
    // The body of the method should contain one or more await expressions. 

    // Return statement specifies an integer result. 
    return hours; 
} 

    // Calls to TaskOfTResult_MethodAsync from another async method. 
private async void CallTaskTButton_Click(object sender, RoutedEventArgs e) 
{ 
    Task<int> returnedTaskTResult = TaskOfTResult_MethodAsync(); 
    int intResult = await returnedTaskTResult; 
    // or, in a single statement 
    //int intResult = await TaskOfTResult_MethodAsync(); 
} 






// Signature specifies Task 
async Task Task_MethodAsync() 
{ 
    // . . . 
    // The body of the method should contain one or more await expressions. 

    // The method has no return statement. 
} 

    // Calls to Task_MethodAsync from another async method. 
private async void CallTaskButton_Click(object sender, RoutedEventArgs e) 
{ 
    Task returnedTask = Task_MethodAsync(); 
    await returnedTask; 
    // or, in a single statement 
    //await Task_MethodAsync(); 
} 
+0

http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features –

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