Использование операторов и ключевых слов await прекрасно работает в с #

102

У меня есть ситуация, когда я asyncвызываю метод, который возвращает и IDisposableэкземпляр. Например:

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

До asyncэтого при работе с IDisposableэкземпляром этот вызов и код, который использовал переменную «response», были бы заключены в оператор using.

Мой вопрос в том, является ли это все еще правильным подходом, когда asyncв смесь добавляется ключевое слово? Несмотря на то, что код компилируется, будет ли оператор using работать должным образом в обоих приведенных ниже примерах?

Пример 1

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

    return true;
}

Пример 2

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

    return true;
}
качели
источник

Ответы:

98

Да, все должно быть хорошо.

В первом случае вы действительно говорите:

  • Асинхронно подождите, пока мы не получим ответ
  • Используйте его и немедленно утилизируйте

Во втором случае вы говорите:

  • Асинхронно подождите, пока мы не получим ответ
  • Асинхронно подождите, пока мы не зарегистрируем ответ
  • Избавьтесь от ответа

usingЗаявление в методе асинхронном является «нечетным» в том , что Disposeвызов может выполняться в другом потоке к той , которая приобрела ресурс ( в зависимости от контекста синхронизации и т.д.) , но он все равно будет происходить ... предполагая , что вы ждете когда-нибудь появится или потерпит неудачу, конечно. (Точно так же, как вы не Disposeвызовете неасинхронный код, если ваш usingоператор содержит вызов метода, который никогда не возвращается.)

Джон Скит
источник
4
Спасибо, Джон. Хотя большинство асинхронных вещей для меня все еще вуду, довольно обнадеживает то, как часто они интегрируются с другими функциями .net и просто работают
swingdoctor
@JonSkeet Следует ли использовать await даже внутри using(){...}блока, или это будет излишним или в некоторых случаях может снизить производительность? Служит using(){...}той же цели, что и await?
nam
1
@nam: Нет, usingи awaitслужат совершенно другим целям. Обратите внимание, что C # 8 теперь также имеет асинхронное удаление. Хотя это стоит быть в курсе вопроса заправочной мой ответ подчеркивает, что , безусловно , не означает , что это неправильно смешивать usingи await.
Джон Скит,