2013-03-16 9 views
9

Ho due seguenti metodiIl metodo che ottiene Task e lo passa lo attende?

public async Task<bool> DoSomething(CancellationToken.token) 
{ 
    //do something async 
} 

//overload with None token 
public /*async*/ Task<bool> DoSomething() 
{ 
    return /*await*/ DoSomething(CancellationToken.None); 
} 

Dovrei secondo metodo essere contrassegnati con async/attendere parole chiave o no?

risposta

12

Non è necessario: in questo caso, se si utilizza Attesa/Asincrona nel secondo metodo, verrà aggiunto un sovraccarico aggiuntivo che non porta a nulla.

Il lavoro asincrono all'interno di DoSomething(CancellationToken) fornirà già la corretta gestione asincrona e il marshalling al contesto esistente.

Alla fine della giornata, async e await sono davvero solo le funzionalità del linguaggio che semplificano la creazione e la composizione di Task. Se hai già un ottimo Task da restituire, non è necessario utilizzare il supporto lingua aggiuntivo per scartarlo e reinserirlo in un nuovo Task.

+0

Se contrassegno il metodo come asincrono e attendo prima di tornare, appena prima del ritorno posso scrivere un codice di cortocircuito come "if (someCondition) return false" .. Senza la parola chiave async questo non è possibile perché si lamenta tipo di risposta non corrispondente ... Che cosa consiglieresti in questo caso? Usa Task.FromResult ?? O è asincrono attendere avvolgimento bene in questo caso? – labroo

+2

@labroo In questo caso, probabilmente userò "Task.FromResult". – hazzik

11

Per aggiungere alla buona risposta di Reed, pensare in questo modo:

Func<int, int> GetFunc() 
{ 
    Func<int, int> f = GetFunc(someParameter); 

caso dire

return f; 

o ragione "Dovrei essere di ritorno a func qui, quindi cerchiamo di fare un lambda che chiama la funzione che ho in mano ":

return (int i) => f(i); 

Spero che tu faccia il primo; hai già un Func<int, int> in mano, quindi basta restituirlo. Non eseguire una funzione che richiama una funzione.

Se trovassi

IEnumerable<int> GetSequence() 
{ 
    IEnumerable<int> sequence = GetSequence(someParameter); 

diresti

return sequence; 

o

foreach(int item in sequence) yield return item; 

? Ancora una volta, spero che tu faccia il primo. Hai una sequenza in mano, quindi perché passare a tutta la fatica di fare una nuova sequenza che enumeri quella vecchia?

Lo stesso vale per le attività; proprio come è possibile creare un delegato che avvolge un altro delegato e una sequenza che avvolge un'altra sequenza, è possibile creare un'attività che avvolga un'altra attività, ma perché? È solo uno spreco di risorse.

+0

È interessante notare che ReSharper rileva (e offre la correzione automatica) del codice che rende uno di questi due errori. Non sono sicuro se rileverà il caso dell'OP. – Brian

+3

@Brian: interessante. Quest'ultimo caso non è probabilmente un bug perché ha un effetto; in primo luogo, assicura che la sequenza risultante non abbia identità referenziale con la sequenza sorgente e, in secondo luogo, assicura che la seconda sequenza sia * sola lettura * anche se la sequenza sorgente non lo è. –

Problemi correlati