2016-04-08 12 views
5

Supponiamo che abbia un metodo che attende un'attività. Questo metodo restituisce anche un'attività. Per esempio:Cosa dovrebbe fare un metodo asincrono se un'attività viene eseguita condizionatamente?

public async virtual Task Save(String path) 
{ 
    if (NewWords.Any()) 
    { 
     await FileManager.WriteDictionary(path, NewWords, true); 
    } 
    else await Task.Run(() => { }); 
} 

È il

else await Task.Run(() => { }); 

necessario qui o sono libero di lasciarlo? C'è qualche differenza se è presente/assente? Forse c'è qualche altro approccio a questo che dovrei prendere?

+1

Dicci perché hai inserito quel codice. Non è necessario ed è la prova che devi fraintendere qualcosa. Hai bisogno di scoprire di cosa si tratta. – usr

+1

Non è necessario ed è anche dannoso. – IllidanS4

+0

NON UTILIZZARE 'Task.Run' IN ATTUAZIONE! http://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html – Aron

risposta

4

È peggio di inutile, mentre stai facendo girare una discussione per non fare nulla e poi aspettare fino a quando non ha finito di fare nulla.

Il modo più semplice per non fare nulla è non fare nulla. In un metodo async il metodo sarà ancora sono tornati un Task, ma che Task sarà completato già, in modo da qualcosa await ing che più in alto si arriva direttamente sulla prossima cosa che deve fare:

public async virtual Task Save(String path) 
{ 
    if (NewWords.Any()) 
    { 
     await FileManager.WriteDictionary(path, NewWords, true); 
    } 
} 

(Inoltre, sarebbe più in linea con la convenzione se SaveAsync e WriteDictionaryAsync fossero i nomi dei metodi qui). Se non si utilizza async (e non c'è bisogno di qui, ma capisco che è un esempio) utilizzare Task.CompletedTask:

public virtual Task Save(String path) 
{ 
    if (NewWords.Any()) 
    { 
     return FileManager.WriteDictionary(path, NewWords, true); 
    } 
    return Task.CompletedTask; 
} 

Se si esegue la codifica a fronte di un quadro prima di 4.6 e, pertanto, non hanno CompletedTask disponibile, Task.Delay(0) è utile come Delay casi particolari il valore 0 per restituire un'attività completata cache (in realtà, la stessa che CompletedTask rendimenti):

public virtual Task Save(String path) 
{ 
    if (NewWords.Any()) 
    { 
     return FileManager.WriteDictionary(path, NewWords, true); 
    } 
    return Task.Delay(0); 
} 

Ma il modo 4.6 è più chiaro come i vostri inten t, piuttosto che dipendere da un capriccio di implementazione.

+0

Grazie per la spiegazione, questo mi ha aiutato a ripulirlo. Ero un po 'perplesso riguardo al compilatore, permettendomi di non restituire nulla su qualche percorso di codice (nonostante fosse consapevole che Task è il risultato di un'operazione di background che restituisce il vuoto). Immagino che il compilatore lo tratti in modo univoco come se fosse vuoto, giusto? –

+0

Praticamente. Il punto di 'async' è di lasciarci scrivere metodi che restituiscono compiti con sequenze potenzialmente piuttosto complicate di attesa su altri compiti, proprio come scriveremmo il metodo sincrono equivalente. Quindi, proprio come un metodo sincrono che non fa nulla può essere vuoto (o vuoto in un dato ramo) così può un 'asincrono' che restituisce appena un compito completato. Quello che succede in realtà è che viene creata una macchina a stati e simile a come 'yield' viene trasformato in' MoveNext() ', quindi questo ha un' MoveNext() 'che viene chiamato una volta all'inizio e poi dopo ogni attività che hai 'await'ed restituisce ... –

+0

... nel caso di seguire un percorso che non ha colpito un' attendi', la prima chiamata in quel 'MoveNext()' indica che è stato eseguito.Il 'Task' che usa quella macchina a stati (che è ciò che realmente restituisce il tuo metodo) viene quindi messo in uno stato completato. Poiché il primo 'MoveNext()' succede prima che il 'Task' sia completato (e in effetti tutti gli altri se tutti gli' attendi 'colpiscono sulle attività completate e non devono attendere realmente), l'attività viene completata già al momento della restituzione. –

5

Non è necessario. async è necessario solo se si utilizza almeno uno await. Tutto all'interno del metodo viene eseguito in modo sincrono ad eccezione di await e cosa fa dopo.

Problemi correlati