2016-01-15 17 views
7

Dato un metodo comeattendono attendono vs Unwrap()

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

Qual è la differenza tra

await await ActionAsync(); 

e

await ActionAsync().Unwrap(); 

se presente.

+1

'attendono ActionAsync() Separa();' è sicuramente più facile da leggere tra i due.. Questo è dove finiscono le differenze. –

+1

Aggiungi benchmark al mio asnwer. –

risposta

15

Unwrap() crea una nuova istanza di attività che rappresenta l'intera operazione su ogni chiamata. Al contrario, l'attività await creata in questo modo è diversa dall'attività interna originale. Vedi le Unwrap() documenti, e prendere in considerazione il seguente codice:

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); 
} 

uscita è:

True 
False 

Aggiornamento con punto di riferimento per NET 4.5.1: Ho provato entrambe le versioni, e si scopre che la versione con doppio await è migliore in termini di utilizzo della memoria. Ho usato il profiler di memoria di Visual Studio 2013. Il test include 100.000 chiamate di ogni versione.

x64:

╔══════════════════╦═══════════════════════╦═════════════════╗ 
║ 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

Apprezzo molto la risposta dettagliata, i campioni di codice e persino i benchmark! Davvero splendido. – hatcyl

4

Non ci saranno differenze funzionali.

+0

grazie per aver confermato, lo accetterò presto. Nel frattempo, qualsiasi riferimento a questa affermazione? – hatcyl

+1

@hatcyl Di quale riferimento hai bisogno? 'await' svolge un'attività. Questo è * quello che fa *. Sono uguali * per definizione *. – Servy

+0

@hatcyl 'Unwrap' restituisce una nuova attività che rappresenta l'attività interna di un' Task '. Sarà in grado di restituire un simile compito praticamente immediatamente; non sarà un'operazione di blocco. Se le attività restituite da entrambi non fossero identiche, sarebbe un errore in uno dei due processi. – Servy

Problemi correlati