异步一直向下?

时间:2012-08-18 06:12:24

标签: c# async-await c#-5.0

试图理解新的异步/等待模式,我有一个问题,我找不到答案,即如果我打算用异步装饰我的方法,如果我打算从其他异步函数调用这些方法,或者只需在适当的地方返回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关键字。

2 个答案:

答案 0 :(得分:9)

两个版本的工作效率相同,唯一的区别是当你在这里使用await时,会受到一些性能损失(因为必须设置状态机并且最有可能使用延续)。 / p>

因此,它取决于权衡:您是否希望您的方法更有效,但代价是可读性稍差?或者你愿意为了可读性而牺牲性能吗?

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

另请注意,您的课程C仍然不够远:foo1()也不需要await

答案 1 :(得分:2)

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

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