Подтвердить что ты не робот

Асинхронно все вниз?

Попытка понять новый шаблон async/await, у меня есть один вопрос, на который я не могу найти ответ, а именно, если я должен украсить мои методы с помощью async, если я намереваюсь вызывать эти методы из других асинхронных функций или просто верните Task где это необходимо?

Другими словами, какой из этих классов A, B или C является лучшим и почему?

class A<T>
{
      public async Task<T> foo1() //Should be consumed
      {
          return await foo2();
      }

      public async Task<T> foo2() //Could be consumed
      {
          return await foo3();
      }

      private async Task<T> foo3() //Private
      {
          return await Task.Run(...);
      }
}

class B<T>
{
      public async Task<T> foo1() //Should be consumed
      {
          return await foo2();
      }

      public async Task<T> foo2() //Could be consumed
      {
          return await foo3();
      }

      private Task<T> foo3() //Private
      {
          return Task.Run(...);
      }
}

class C<T>
{
      public async Task<T> foo1() //Should be consumed
      {
          return await foo2();
      }

      public Task<T> foo2() //Could be consumed
      {
          return foo3();
      }

      private Task<T> foo3() //Private
      {
          return Task.Run(...);
      }
}

Кажется излишним переопределять методы, поэтому я, естественно, склоняюсь к C, но в то же время мне неловко работать с Task<T>, если вы не используете ключевое слово await.

4b9b3361

Ответ 1

Обе версии работают эффективно одинаково, единственное отличие состоит в том, что при использовании await здесь вы получаете некоторое ограничение производительности (потому что конечный автомат должен быть настроен и, скорее всего, будет использоваться продолжение).

Итак, это сводится к компромиссу: вы хотите, чтобы ваши методы были несколько эффективнее за счет того, чтобы быть менее читабельными? Или вы готовы принести в жертву производительность для удобочитаемости?

Обычно, я бы посоветовал сначала перейти на читаемость и сосредоточиться только на производительности, если профилирование говорит вам об этом. Но в этом случае я думаю, что увеличение удобочитаемости мало, поэтому я бы, вероятно, не использовал await.

Также обратите внимание, что ваш класс C все еще не достаточно далеко: foo1() также не нужен await.

Ответ 2

async в сигнатуре есть возможность разрешить компилятору создать перезапись состояния машины содержащегося кода, необходимого для реализации семантики await в общем случае.

Ваш пример - это особый случай, когда вам не нужна эта переписывание: асинхронная операция - это последнее, что происходит внутри метода. Такой метод уже возможен и действителен в .NET4.0. Эта совместимость может быть одной из причин избежать async, когда она вам не нужна.