Usa le istruzioni e attendi che le parole chiave funzionino bene in c #


101

Ho una situazione in cui sto effettuando una asyncchiamata a un metodo che restituisce e IDisposableistanza. Per esempio:

HttpResponseMessage response = await httpClient.GetAsync(new Uri("http://www.google.com"));

Ora prima asyncera sulla scena, quando si lavora con IDisposableun'istanza, questa chiamata e il codice che utilizzava la variabile "response" sarebbero stati racchiusi in un'istruzione using.

La mia domanda è se questo è ancora l'approccio corretto quando la asyncparola chiave viene lanciata nel mix? Anche se il codice viene compilato, l'istruzione using funzionerà ancora come previsto in entrambi gli esempi seguenti?

Esempio 1

using(HttpResponseMessage response = await httpClient.GetAsync(new Uri("http://www.google.com")))
{
    // Do something with the response

    return true;
}

Esempio 2

using(HttpResponseMessage response = await httpClient.GetAsync(new Uri("http://www.google.com")))
{
    await this.responseLogger.LogResponseAsync(response);

    return true;
}

Risposte:


97

Sì, dovrebbe andare bene.

Nel primo caso, stai davvero dicendo:

  • Attendi in modo asincrono finché non possiamo ottenere la risposta
  • Usalo e smaltiscilo immediatamente

Nel secondo caso, stai dicendo:

  • Attendi in modo asincrono finché non possiamo ottenere la risposta
  • Attendi in modo asincrono finché non abbiamo registrato la risposta
  • Smaltire la risposta

Una usingdichiarazione in un metodo asincrono è "strano", in quanto la Disposechiamata può eseguire in un thread diverso da quello che ha acquisito la risorsa (a seconda del contesto, la sincronizzazione, ecc), ma sarà ancora accadere ... supponendo che la cosa si sta aspettando si presenta o fallisce, ovviamente. (Proprio come non finirai per chiamare Disposein codice non asincrono se la tua usingdichiarazione contiene una chiamata a un metodo che non ritorna mai.)


4
Grazie Jon. Sebbene la maggior parte delle cose asincrone siano ancora voodoo per me, è abbastanza rassicurante vedere quanto spesso si integra con altre funzionalità di .net e funziona
swingdoctor

@ JonSkeet Dovrebbe essere utilizzato anche in un using(){...}blocco o è eccessivo o in alcuni casi può peggiorare le prestazioni? Ha using(){...}lo stesso scopo di await?
nam

1
@nam: No, usinge awaitservono a scopi completamente diversi. Si noti che C # 8 ora ha anche l'eliminazione asincrona. Anche se vale la pena essere consapevoli del problema del threading evidenziato dalla mia risposta, ciò non significa assolutamente che sia sbagliato mescolare usinge await.
Jon Skeet
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.