2012-09-03 12 views
14

Se ho un metodo normale che voglio fare asincrona:Perché utilizzare async e attendere con l'attività <>?

public int Foo(){} 

lo farei:

public Task<int> FooAsync(){ 
    return Task.Run(() => Foo()); 
} 

Perché dovrei fare:

public async Task<int> FooAsync(){ 
    return await Task.Run(() => Foo()); 
} 

Il modo ho intenzione di utilizzare questo è:

FooAsync().ContinueWith((res) => {}); 

Voglio che il metodo sia eseguito senza fermarsi, ma voglio che venga attivato un callback, quindi lo ContinueWith. Ma con la seconda versione, c'è un punto per usarlo?

risposta

14

Nella mia comprensione, avete solo bisogno di async e await quando si scrive un metodo che fa un po 'di chiamate asincrone all'interno, ma si vorrebbe che sguardo come se non lo fa. In altre parole, si desidera scrivere e leggere il codice come se fosse un normale codice sequenziale, gestire le eccezioni come se fosse un normale codice sequenziale, restituire valori come se fosse un normale codice sequenziale e così via. Quindi la responsabilità del compilatore è di riscrivere quel codice con tutti i callback necessari preservando la logica.

Il tuo metodo è così semplice Non credo che sia necessario riscriverlo, puoi semplicemente restituire l'attività, ma chiunque la consuma potrebbe volere await per il suo valore di ritorno.

+0

descrizione eccellente! – paulsm4

+0

Grazie, @ paulsm4. Devo dire che sto solo raccontando quello che ho sentito di recente, penso, è dal http://hanselminutes.com/327/everything-net-programmers-know-about-asynchronous-programming-is-wrong, ma non sicuro al 100%. Non avevo ancora molta esperienza con la funzione asincrona, quindi potrei sbagliarmi e sarei felice di saperne di più, forse async offre alcuni vantaggi in questo caso. –

+2

Inoltre, potresti voler leggere [Devo esporre i wrapper asincroni per i metodi sincroni?] (Http://blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx) (La risposta quasi sempre è "no;" se si dispone di un metodo sincrono, quindi dargli una firma del metodo sincrono). –

5

Perché dovrei fare:

public async Task<int> FooAsync() 
{ 
    return await Task.Run(() => Foo()); 
} 

Non lo faresti. La tua versione precedente restituisce Attività che è già in attesa. Questa nuova versione non aggiunge nulla.

Il modo ho intenzione di utilizzare questo è:

FooAsync().ContinueWith((res) => {}); 

voglio il metodo di funzionare solo senza fermarsi, ma voglio qualcosa come un callback per essere licenziato, da cui il ContinueWith.

Questo è dove la differenza viene in Diamo rimpolpare il vostro esempio un po ':.

void DoAsyncStuff() 
{ 
    FooAsync().ContinueWith((res) => { DoSomethingWithInt(res.Result) }); 
} 

Utilizzando async, è possibile scrivere lo stesso codice come questo:

void async DoAsyncStuff() 
{ 
    int res = await FooAsync(); 
    DoSomethingWithInt(res); 
} 

Il il risultato è lo stesso. La parola chiave await trasforma il resto del tuo metodo in una continuazione che viene ripresa dopo che FooAsync produce un valore. È proprio come il tuo altro codice, ma più facile da leggere. * shrug *

+0

Il metodo 'async' in realtà non dovrebbe essere annullato restituendo. I metodi 'async' dovrebbero essere annullati solo quando saranno un gestore di un evento. Dovrebbe restituire 'Task' se non ci sono valori di ritorno nel metodo. A parte questo, posto abbastanza decente. – Servy

+0

@Servy "i metodi asincroni dovrebbero essere annullati solo quando saranno un gestore di un evento." Questo è il caso qui, giusto? Cosa dovrebbe restituire 'DoAsyncStuff' in questo esempio e dove otterrebbe quel valore senza scrivere codice superfluo? Inoltre, se un metodo asincrono restituisce Task e tu * non * lo aspetti, ricevi un avviso del compilatore (CS4014), che è fastidioso. Recentemente [ho chiesto informazioni su questo problema] (http://stackoverflow.com/questions/14903887/warning-this-call-is-not-waited-execution-of-the-current-method-continues) qui. Se hai una risposta migliore, potresti postarla lì? – Mud

+0

Quando un metodo 'async' restituisce vuoto esso lo rende essenzialmente un metodo" fire and forget ". Il chiamante non ha modo di sapere quando il metodo finisce effettivamente. Non c'è alcuna indicazione dal codice OP qui che è quello che vuole. Per quanto riguarda l'avviso del compilatore, è perché quasi certamente * non vuoi farlo *, come ti ho detto nel post a cui ti sei collegato; l'avviso è * correttamente * indicando che c'è un difetto nel tuo progetto, e che le probabilità sono che non vuoi il comportamento che stai ricevendo. Sebbene tu possa volere quel comportamento in alcuni casi limite, sostengo le mie affermazioni. – Servy

Problemi correlati