2012-08-02 17 views
13

Sto scrivendo una libreria che avvolge una chiamata di servizio Web di terze parti e sto cercando di fare in modo che la libreria utilizzi le nuove funzionalità asincrone/attese. Qual è l'uso corretto delle parole chiave asincrone/attese nel seguente esempio?Nesting async/await methods

public class MyApi 
{ 
    public Task<ApiResult> DoSomethingAsync() 
    { 
     return this.DoSomethingCore(); 
    } 

    public async Task<ApiResult> DoSomethingElseAsync() 
    { 
     return await this.DoSomethingCore(); 
    } 

    private async Task<ApiResult> DoSomethingCore() 
    { 
     var httpClient = new HttpClient(); 
     var httpResponseMessage = await httpClient.GetAsync("some url"); 
     var rawResultText = await httpResponseMessage.Content.ReadAsStringAsync(); 
     return new ApiResult(rawResultText);   
    } 
} 

Per consentire il mio interlocutore di attendere il metodo DoSomethingAsync, dovrebbe quel metodo hanno anche l'asincrono e attendono le parole chiave aggiunto ad esso? O va bene così com'è perché restituisce un compito? C'è un modello migliore per questo tipo di nidificazione?

Penso che il metodo DoSomethingAsync sia il modo corretto di andare qui, è corretto? Credo che DoSomethingElseAsync sembri l'approccio sbagliato quando si costruisce una libreria.

+0

C# 5.0 non esiste, la versione successiva è 4.5, vuoi dire questo? –

+9

@Ramhound - Il prossimo CLR è 4.5, la lingua successiva è C# 5 –

risposta

8

Qualsiasi Task può essere atteso, indipendentemente da dove proviene.

io non sono sicuro perché DoSomethingAsync chiamate solo DoSomethingCore, dal momento che DoSomethingAsync potrebbe benissimo essere async e utilizzare await.

C'è anche un general rule che si dovrebbe usare ConfigureAwait(false) in metodi di libreria.

Edit: Se non è necessario utilizzare await, allora non rendere il metodo async. async aggiungerà un po 'di overhead (controlla Channel9 per il video Zen of Async Performance di Stephen Toub). Se puoi semplicemente restituire un Task (come DoSomethingAsync), allora fallo in questo modo.

+0

DoSomethingAsync chiama DoSomethingCore perché nel mio scenario reale, ho due metodi pubblici simili che condividono la funzionalità utilizzando un metodo core. Analizzerò il metodo ConfigureAwait, come non avevo mai visto prima. –

+0

Ho aggiunto un metodo DoSomethingElseAsync() per spiegare meglio di cosa ero confuso. Credo che tu abbia spiegato questo sufficientemente e che il metodo DoSomethingAsync() sia la strada da percorrere per un metodo di libreria. –

+0

OK. Vedi risposta aggiornata. –

0

La formulazione di seguito è funzionale, ma probabilmente causerà un ulteriore sovraccarico (a causa di avere un callback secondario per l'async aggiuntive/attendere metodo.)

public async Task<ApiResult> DoSomethingElseAsync() 
{ 
    return await this.DoSomethingCore(); 
} 

è più semplice tornare direttamente Task, come si può attendo sempre tale compito altrove senza dover implementare il metodo come 'asincrono'. Async/Wait è molto simile all'utilizzo di "yield return"; fa un po 'di magia del compilatore per implementare il' yielding ', ma l'enumerazione stessa non si cura di come la si implementa. Allo stesso modo, una chiamata di "attesa" non interessa come funziona l'attesa, purché sia ​​attendibile.