C# 一路异步?

C# 一路异步?,c#,async-await,c#-5.0,C#,Async Await,C# 5.0,为了理解新的async/await模式,我有一个问题找不到答案,即我是否应该用async修饰我的方法,是否打算从其他async函数调用这些方法,或者只是在适当的情况下返回Tasks 换句话说,A、B或C类中哪一类最好,为什么 class A<T> { public async Task<T> foo1() //Should be consumed { return await foo2(); } pub

为了理解新的async/await模式,我有一个问题找不到答案,即我是否应该用async修饰我的方法,是否打算从其他async函数调用这些方法,或者只是在适当的情况下返回
Task
s

换句话说,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(...);
      }
}
A类
{
公共异步任务foo1()//应被使用
{
返回等待foo2();
}
公共异步任务foo2()//无法使用
{
返回等待foo3();
}
私有异步任务foo3()//私有
{
返回等待任务。运行(…);
}
}
B类
{
公共异步任务foo1()//应被使用
{
返回等待foo2();
}
公共异步任务foo2()//无法使用
{
返回等待foo3();
}
私有任务foo3()//私有
{
返回任务。运行(…);
}
}
C类
{
公共异步任务foo1()//应被使用
{
返回等待foo2();
}
公共任务foo2()//无法使用
{
返回foo3();
}
私有任务foo3()//私有
{
返回任务。运行(…);
}
}

过度简化方法似乎是多余的,所以我自然倾向于
C
,但同时,除非您使用
await
关键字,否则使用
Task
会感到有些尴尬。

签名中的
async
允许编译器创建状态机重写所包含的代码,这是在一般情况下实现
await
语义所必需的案例


您的示例正是不需要重写的特殊情况:异步操作是方法中发生的最后一件事。这种方法在
.NET4.0
中已经是可行和有效的。当您不需要时,这种兼容性可能是避免使用
async
的原因之一。

两个版本的工作原理相同,唯一的区别是,当您在此处使用
wait
时,您会受到一些性能损失(因为必须设置状态机,并且很可能会使用延续)

因此,这归结为一个折衷:您是否希望您的方法在某种程度上更高效,而代价是可读性稍差?还是为了可读性而牺牲性能

通常,我会建议您首先考虑可读性,如果评测告诉您这是值得的,那么只关注性能。但是在这种情况下,我认为可读性的增加很小,所以我可能不会使用
wait


还要注意,您的类
C
仍然不够深入:
foo1()
也不需要
wait

+1。尽管我要更强烈地说,它们不应该都是异步的。依我看,这并不是不可读的。。。也就是说,如果读者理解它是可等待的方法的返回类型,而不是方法本身。顺便说一句,短语“async all the way down”通常意味着您需要。此代码-即使不使用
async
关键字-仍然是完全异步的。(顺便说一句,在我看来,我第一次听到Lucian Wischik使用这个短语,但现在我在Stephen Toub的博客条目之前找不到用法)。这就是为什么我希望没有添加async关键字要求的原因。我理解“可能会在某个地方破坏现有代码”,但与能够选择使用yield return进行另一次编译器重写相比,它会导致这样的问题/困惑:)