Делайте с использованием утверждений и ожидайте ключевых слов, играющих красиво в С#

У меня возникла ситуация, когда я вызываю вызов 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;
}

Ответ 1

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

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

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

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

  • Асинхронно ждать, пока мы не сможем получить ответ
  • Асинхронно ждать, пока мы не выполним ответ
  • Устранить ответ
Оператор

A using в асинхронном методе является "нечетным" в том смысле, что вызов Dispose может выполняться в другом потоке с тем, который приобрел ресурс (в зависимости от контекста синхронизации и т.д.), но это все равно произойдет. Предполагаю, что вещь, которую вы ждете навсегда, проявляет или терпит неудачу, конечно. (Так же, как вы не закончите вызов Dispose в неасинхронном коде, если ваш оператор using содержит вызов метода, который никогда не возвращается.)