2013-07-26 9 views
28

Na końcu metody asynchronicznej zwracającej zadania, jeśli wywołam inną metodę asynchroniczną, mógłbym wykonać to zadanie jako await lub return. Jakie są konsekwencje każdego z nich?Na zakończenie metody asynchronicznej powinienem zwrócić lub poczekać?

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

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

Może to być niebezpieczne, jeśli połączysz je z 'using':' using (something) {return BazAsync(); } 'i' using (something) {czekaj na BazAsync(); } 'zachowuj się bardzo różnie. – svick

+0

Powiązanie podobnego pytania: http://stackoverflow.com/q/21033150/1768303 – Noseratio

+2

Napisałem post na blogu o [zaletach i pułapkach eliding 'async' /' await'] (http: //blog.stephencleary. com/2016/12/eliding-async-await.html). –

Odpowiedz

29

Nie można powrócić zadanie jeśli sama metoda jest uznane za async - tak to nie będzie działać, na przykład :

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

Wymagałoby to typu zwrotu Task<Task>.

Jeśli metoda jest tylko robi niewielką ilość pracy, a następnie wywołanie tylko metody asynchronicznej jeden, wówczas pierwsza opcja jest w porządku, i oznacza, że ​​istnieje jeden mniej zadaniem zaangażowany. Należy mieć świadomość, że wszelkie wyjątki generowane w ramach metody synchronicznej będą dostarczane synchronicznie - w istocie wolę obsługiwać sprawdzanie poprawności argumentów.

Jest to również powszechny wzorzec do implementacji przeciążania, np. przez token anulowania.

Pamiętaj, że jeśli musisz zmienić, aby poczekać na coś innego, musisz zamiast tego zastosować metodę asynchroniczną. Na przykład:

// 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

'Jeśli twoja metoda polega jedynie na wykonaniu niewielkiej ilości pracy, a następnie wywołaniu tylko jednej metody asynchronicznej" In w szczególności jest to typowy wzorzec przeciążania metod "asynchronicznych" (np. 'BarAsync()' i 'BarAsync (CancellationToken)'). –

+1

@StephenCleary: Rzeczywiście - i podobnie sprawdza się synchronicznie, a następnie zwraca "prawdziwe" zadanie asynchroniczne. Zostanie zmienione, aby to zaznaczyć. –

+0

@JonSkeet, przepraszam za odświeżenie tego po 3 latach, ale pytanie - za każdym razem, gdy widzę kod, który nie ma "poczekaj" i po prostu zwraca "zadanie", jeśli jest wyjątek podczas tego zadania, czasami wydaje się, że "znikają" ", nawet jeśli osoba oczekująca oczekuje na zadanie. Czy jest to związane z Twoim komentarzem na temat wyjątków wysyłanych synchronicznie? – Cody

1

Wyjazd ten link gdzie jest to opisane: 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 –

Powiązane problemy