2016-01-15 16 views
7

Biorąc pod uwagę sposób, taki jakczekają oczekiwać vs odwinąć()

public async Task<Task> ActionAsync() 
{ 
    ... 
} 

co stanowi różnicę pomiędzy

await await ActionAsync(); 

i

await ActionAsync().Unwrap(); 

jeśli występują.

+1

'czekają ActionAsync() Unwrap();' jest zdecydowanie łatwiejsze do odczytania między nimi.. Chodzi o to, gdzie kończą się różnice. –

+1

Dodaj testy porównawcze do mojego asnwer. –

Odpowiedz

15

Unwrap() tworzy nową instancję zadania, która reprezentuje całą operację dla każdego połączenia. W przeciwieństwie do zadania utworzonego w ten sposób różni się od oryginalnego zadania wewnętrznego. Zobacz Unwrap() docs i rozważyć następujący kod:

private async static Task Foo() 
{ 
    Task<Task<int>> barMarker = Bar(); 

    Task<int> awaitedMarker = await barMarker; 
    Task<int> unwrappedMarker = barMarker.Unwrap(); 

    Console.WriteLine(Object.ReferenceEquals(originalMarker, awaitedMarker)); 
    Console.WriteLine(Object.ReferenceEquals(originalMarker, unwrappedMarker)); 
} 

private static Task<int> originalMarker; 
private static Task<Task<int>> Bar() 
{ 
    originalMarker = Task.Run(() => 1);; 
    return originalMarker.ContinueWith((m) => m); 
} 

wyjścia:

True 
False 

aktualizacja z odniesienia dla .NET 4.5.1: testowałem obie wersje, a okazuje się, że Wersja z podwójnym await jest lepsza pod względem wykorzystania pamięci. Użyłem profilera pamięci Visual Studio 2013. Test obejmuje 100 000 połączeń każdej wersji.

64:

╔══════════════════╦═══════════════════════╦═════════════════╗ 
║ Version   ║ Inclusive Allocations ║ Inclusive Bytes ║ 
╠══════════════════╬═══════════════════════╬═════════════════╣ 
║ await await  ║ 761     ║ 30568   ║ 
║ await + Unwrap() ║ 100633    ║ 8025408   ║ 
╚══════════════════╩═══════════════════════╩═════════════════╝ 

x86:

╔══════════════════╦═══════════════════════╦═════════════════╗ 
║ Version   ║ Inclusive Allocations ║ Inclusive Bytes ║ 
╠══════════════════╬═══════════════════════╬═════════════════╣ 
║ await await  ║ 683     ║ 16943   ║ 
║ await + Unwrap() ║ 100481    ║ 4809732   ║ 
╚══════════════════╩═══════════════════════╩═════════════════╝ 
+0

Naprawdę doceniam szczegółową odpowiedź, próbki kodu, a nawet testy porównawcze! Bardzo niesamowite. – hatcyl

4

Nie będzie żadnych różnic funkcjonalnych.

+0

dzięki za potwierdzenie, wkrótce zaakceptuję. W międzyczasie, wszelkie odniesienia do tego oświadczenia? – hatcyl

+1

@chychl Jaką referencję potrzebujesz? 'Czekaj' rozpakowuje zadanie. To * co robi *. Są równe * z definicji *. – Servy

+0

@hatcyl 'Unwrap' zwraca nowe zadanie reprezentujące wewnętrzne zadanie' Task '. Będzie w stanie zwrócić takie zadanie praktycznie natychmiast; nie będzie to operacja blokująca. Jeśli zadania zwrócone przez którekolwiek z nich nie byłyby identyczne, byłby to błąd w jednym z dwóch procesów. – Servy