2016-02-04 29 views
13

Supponiamo di avere un controller C# che chiama in una funzione arbitraria che restituisce un'attività (ad esempio perché esegue una transazione di database). Dovrei sempre usare async e attendere, o dovrei semplicemente restituire l'attività?Devo usare async/attendere per ogni metodo che restituisce un'attività

regolatore Esempio:

public async Task<string> DoSomething() { 
    return await SomeOtherFunctionThatReturnsATask(); 
} 

Devo cambiare questo in:

public Task<string> DoSomething() { 
    return SomeOtherFunctionThatReturnsATask(); 
} 

O non è veramente importante?

+0

No. Non c'è bisogno di fare questo per i metodi, a meno che non si desidera utilizzare il valore di ritorno della Task nel metodo stesso. –

+2

[Domanda correlata] (http://stackoverflow.com/questions/19098143/questo-è-la-vita-di-storno-avviso-in-c) e [costo di attesa asincrona] (https: // msdn. microsoft.com/en-us/magazine/hh456402.aspx) –

risposta

18

Sì, è necessario modificare il metodo e rimuovere async/await. La parola chiave async fa sì che il compilatore crei una macchina a stati che gestisca l'attesa per il completamento dell'attività. Quando aspetti un'altra funzione del genere, stai essenzialmente creando due di queste macchine a stati che non sono necessarie. È molto meglio restituire direttamente l'attività dalla seconda funzione e consentire all'utente finale di eseguire l'attesa.

Il modo migliore per capire questo è scrivere un piccolo programma di esempio e decompilarlo. Assicurati che il tuo decompilatore ti mostri tutto il materiale generato dal compilatore (che alcuni nascondono per impostazione predefinita) e sarai in grado di vedere cosa succede tutto lì.

Ecco un rapido esempio ho appena frustato e utilizzati dotPeek di decompilare:

public Task<string> DoSomething() 
{ 
    Class1.\u003CDoSomething\u003Ed__0 stateMachine; 
    stateMachine.\u003C\u003E4__this = this; 
    stateMachine.\u003C\u003Et__builder = AsyncTaskMethodBuilder<string>.Create(); 
    stateMachine.\u003C\u003E1__state = -1; 
    stateMachine.\u003C\u003Et__builder.Start<Class1.\u003CDoSomething\u003Ed__0>(ref stateMachine); 
    return stateMachine.\u003C\u003Et__builder.Task; 
} 

private Task<string> DoSomethingElse() 
{ 
    return Task.FromResult<string>("test"); 
} 

si può vedere la macchina a stati nel primo che mi riferivo. Farà tutto quel lavoro di attesa senza motivo, e quindi il consumatore finale di DoSomething() ripeterà lo stesso lavoro. Realisticamente si dovrebbe usare solo la parola chiave await quando c'è altro codice nel metodo che deve essere eseguito dopo il codice che restituisce l'attività. Perché quel codice ha bisogno di un attendere affinché venga completato prima dell'esecuzione.

codice decompiled completa qui: http://pastebin.com/iJLAFdHZ

+1

Forse intendi "No, non dovresti"? Il titolo della domanda dice "Devo usare async/attendere per ogni metodo"? mentre la tua risposta dice che no questo non dovrebbe essere usato –

+0

@PanagiotisKanavos Immagino che intenda "Sì, dovresti" per questa domanda "Devo cambiare questo in:" –

+3

Ed è per questo che non si dovrebbe fare una domanda diversa nel corpo della domanda dal titolo della domanda. ;) –

Problemi correlati