2016-02-04 12 views
13

Załóżmy, że mam kontrolera C#, który wywołuje pewną dowolną funkcję zwracającą zadanie (na przykład, ponieważ wykonuje transakcję bazy danych). Czy zawsze powinienem używać async i czekać, czy powinienem zwrócić zadanie?Czy powinienem używać async/await dla każdej metody zwracającej zadanie

Przykład kontroler:

public async Task<string> DoSomething() { 
    return await SomeOtherFunctionThatReturnsATask(); 
} 

powinienem zmienić na:

public Task<string> DoSomething() { 
    return SomeOtherFunctionThatReturnsATask(); 
} 

albo nie to naprawdę ważne?

+0

No. Nie trzeba w tym celu metod, chyba że chcesz używać wartości zwracanej zadania w samej metody. –

+2

[Pokrewne pytanie] (http://stackoverflow.com/questions/19098143/what-is-the-pose-of-return-await-in-c) i [koszt asynchronizacji czekają] (https: // msdn. microsoft.com/en-us/magazine/hh456402.aspx) –

Odpowiedz

18

Tak, należy zmienić metodę i usunąć asynchroniczne/czekające. Słowo kluczowe async powoduje, że kompilator tworzy komputer stanu, który zarządza "oczekiwaniem" na zakończenie zadania. Kiedy czekasz na inną taką funkcję, zasadniczo tworzysz dwie z tych maszyn stanów, które są niepotrzebne. Znacznie lepiej jest po prostu zwrócić zadanie z drugiej funkcji bezpośrednio i pozwolić użytkownikowi końcowemu na wykonanie czekania.

Najlepszym sposobem zrozumienia tego jest napisanie małego przykładowego programu i jego dekompilacja. Upewnij się, że twój dekompilator pokazuje ci wszystkie rzeczy generowane przez kompilator (niektóre ukrywają się domyślnie) i będziesz mógł zobaczyć, co się tam dzieje.

Oto krótki przykład Właśnie bita i używane dotPeek dekompilować:

public Task<string> DoSomething() 
{ 
    Class1.\u003CDoSomething\u003Ed__0 stateMachine; 
    stateMachine.\u003C\u003E4__this = this; 
    stateMachine.\u003C\u003Et__builder = AsyncTaskMethodBuilder<string>.Create(); 
    stateMachine.\u003C\u003E1__state = -1; 
    stateMachine.\u003C\u003Et__builder.Start<Class1.\u003CDoSomething\u003Ed__0>(ref stateMachine); 
    return stateMachine.\u003C\u003Et__builder.Task; 
} 

private Task<string> DoSomethingElse() 
{ 
    return Task.FromResult<string>("test"); 
} 

Można zobaczyć maszynę stanów w pierwszym, że miał na myśli. Wykona całą tę pracę oczekując bez powodu, a wtedy końcowy konsument z DoSomething() powtórzy tę samą pracę. Realistycznie powinieneś używać tylko słowa kluczowego await, gdy jest inny kod w metodzie, która musi być uruchomiona po kodzie, który zwraca zadanie. Ponieważ ten kod musi czekać, aby zakończyć przed uruchomieniem.

Pełna decompiled kod tutaj: http://pastebin.com/iJLAFdHZ

+1

Być może masz na myśli "Nie, nie powinieneś"? Tytuł pytania brzmi "Czy powinienem używać asynchronizacji/czekania na każdą metodę"? podczas gdy twoja odpowiedź mówi, że nie, to nie powinno być używane –

+0

@PanagiotisKanavos Myślę, że ma na myśli "Tak, powinieneś" na to pytanie "Czy powinienem to zmienić na:" –

+3

I dlatego nie powinno się zadawać innego pytania w treść pytania z tytułu pytania. ;) –