web-dev-qa-db-fra.com

Utilisez des instructions et attendez que les mots clés jouent bien en c #

J'ai une situation où j'effectue un appel async à une méthode qui renvoie une instance IDisposable. Par exemple:

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

Maintenant, avant que async soit sur la scène, lorsque vous travaillez avec une instance IDisposable, cet appel et le code qui utilisaient la variable "response" seraient encapsulés dans une instruction using.

Ma question est de savoir si c'est toujours la bonne approche lorsque le mot clé async est jeté dans le mix? Même si le code est compilé, l'instruction using fonctionnera-t-elle comme prévu dans les deux exemples ci-dessous?

Exemple 1

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

    return true;
}

Exemple 2

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

    return true;
}
91
swingdoctor

Oui, ça devrait aller.

Dans le premier cas, vous dites vraiment:

  • Attendre de manière asynchrone jusqu'à ce que nous puissions obtenir la réponse
  • Utilisez-le et jetez-le immédiatement

Dans le deuxième cas, vous dites:

  • Attendre de manière asynchrone jusqu'à ce que nous puissions obtenir la réponse
  • Attendez de manière asynchrone jusqu'à ce que nous ayons enregistré la réponse
  • Jeter la réponse

Une instruction using dans une méthode asynchrone est "étrange" dans la mesure où l'appel Dispose peut s'exécuter dans un thread différent de celui qui a acquis la ressource (en fonction du contexte de synchronisation, etc.) mais il le restera arriver ... en supposant que la chose que vous attendez jamais apparaît ou échoue, bien sûr. (Tout comme vous ne finirez pas par appeler Dispose en code non asynchrone si votre instruction using contient un appel à une méthode qui ne revient jamais.)

91
Jon Skeet