Use declarações e espere palavras-chave funcionam bem em c #


101

Eu tenho uma situação em que estou fazendo uma asyncchamada para um método que retorna e IDisposableinstância. Por exemplo:

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

Agora, antes de entrar em asynccena, ao trabalhar com uma IDisposableinstância, essa chamada e o código que usava a variável "resposta" seriam envolvidos em uma instrução using.

Minha pergunta é se essa ainda é a abordagem correta quando a asyncpalavra-chave é incluída no mix? Mesmo que o código seja compilado, a instrução using ainda funcionará conforme o esperado em ambos os exemplos abaixo?

Exemplo 1

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

    return true;
}

Exemplo 2

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

    return true;
}

Respostas:


97

Sim, isso deve estar bem.

No primeiro caso, você está realmente dizendo:

  • Espere de forma assíncrona até que possamos obter a resposta
  • Use-o e descarte-o imediatamente

No segundo caso, você está dizendo:

  • Espere de forma assíncrona até que possamos obter a resposta
  • Espere de forma assíncrona até que tenhamos registrado a resposta
  • Elimine a resposta

Uma usinginstrução em um método assíncrono é "estranha" porque a Disposechamada pode ser executada em uma thread diferente daquela que adquiriu o recurso (dependendo do contexto de sincronização, etc.), mas ainda vai acontecer ... assumindo o que você está esperando sempre aparece ou falha, é claro. (Assim como você não acabará chamando Disposeum código não assíncrono se sua usinginstrução contiver uma chamada para um método que nunca retorna.)


4
Obrigado Jon. Embora a maior parte do material assíncrono ainda seja vodu para mim, é bastante reconfortante ver com que frequência ele se integra a outros recursos .net e simplesmente funciona
swingdoctor

@JonSkeet Deve esperar até mesmo ser usado dentro de um using(){...}bloco ou é um exagero ou pode degradar o desempenho em alguns casos? Tem using(){...}o mesmo propósito que await?
nam

1
@nam: Não, usinge awaitservem a propósitos totalmente diferentes. Observe que o C # 8 agora também tem descarte assíncrono. Embora valha a pena estar ciente do problema de segmentação que minha resposta destaca, isso definitivamente não significa que seja errado misturar usinge await.
Jon Skeet
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.