Use declaraciones y espere a que las palabras clave funcionen bien en c #

101

Tengo una situación en la que hago una asyncllamada a un método que devuelve una IDisposableinstancia. Por ejemplo:

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

Ahora, antes asyncestaba en escena, cuando se trabaja con una IDisposableinstancia, esta llamada y el código que usa la variable "respuesta" se envuelve en una declaración de uso.

Mi pregunta es si ese sigue siendo el enfoque correcto cuando la asyncpalabra clave se agrega a la mezcla. Aunque el código se compile, ¿seguirá funcionando la instrucción using como se esperaba en los dos ejemplos siguientes?

Ejemplo 1

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

    return true;
}

Ejemplo 2

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

    return true;
}
médico de swing
fuente

Respuestas:

97

Si, eso debería estar bien.

En el primer caso, realmente estás diciendo:

  • Espere asincrónicamente hasta que podamos obtener la respuesta
  • Úselo y deséchelo inmediatamente

En el segundo caso, estás diciendo:

  • Espere asincrónicamente hasta que podamos obtener la respuesta
  • Espere asincrónicamente hasta que hayamos registrado la respuesta
  • Disponga de la respuesta

Una usingdeclaración en un método asíncrono es "extraña" en el sentido de que la Disposellamada puede ejecutarse en un hilo diferente al que adquirió el recurso (dependiendo del contexto de sincronización, etc.) pero aún sucederá ... asumiendo lo que está esperando alguna vez aparece o falla, por supuesto. (Al igual que no terminará llamando Disposeen código no asíncrono si su usingdeclaración contiene una llamada a un método que nunca regresa).

Jon Skeet
fuente
4
Gracias Jon. Si bien la mayoría de las cosas asincrónicas siguen siendo vudú para mí, es bastante reconfortante ver con qué frecuencia se integra con otras características de .net y simplemente funciona
swingdoctor
@JonSkeet ¿Debería usarse await incluso dentro de un using(){...}bloque o es una exageración o puede degradar el rendimiento en algunos casos? ¿Tiene using(){...}el mismo propósito que await?
nam
1
@nam: No, usingy awaitsirven para propósitos completamente diferentes. Tenga en cuenta que C # 8 ahora también tiene eliminación asincrónica. Si bien vale la pena estar al tanto del problema de subprocesos que destaca mi respuesta, eso definitivamente no significa que esté mal mezclar usingy await.
Jon Skeet