我应该使用什么作为假人等待?

时间:2015-03-04 09:40:43

标签: c# async-await

我有一个Base类,它提供了一个带有以下签名的方法:

virtual async Task RunAsync()

派生类应该用

之类的方式覆盖此实现
public override async Task RunAsync()
{
  await base.RunAsync();
  await this.DoSomethingElse();
}

现在,编译器向我发出警告,指出Base.RunAsync缺少await语句。我希望我的代码是免费警告,而不是抑制警告,并且它运行而不必提供空检查,即使派生类没有提供覆盖实现,因此使用virtual Task RunAsync()(省略async关键字)是不可能。

现在基本方法中的实现是await Task.Delay(0);,它解除了编译器的警告,但在我看来,它在某种程度上并不“干净”。什么是应对这个主题的正确方法?

1 个答案:

答案 0 :(得分:14)

你误解了async的工作原理。它不是签名的一部分,因此,如果您 await,您实际上不必使用它。因此,即使您提供Task RunAsync()方法,也可以在不使用 async的情况下编写,例如:

virtual Task RunAsync()
{
  return Task.FromResult(false);
}

这仍然允许您进行实际使用await的覆盖,如下所示:

override async Task RunAsync()
{
  await base.RunAsync();
  await DoSomeOtherStuffAsync();
}

这就是编译器为您提供警告的原因 - async关键字完全没用,而不是方法签名的一部分。它只是向编译器发出的一个信号,它允许使用标识符await作为关键字,基本上是为了保持与旧C#代码的向后兼容性。

编辑

正如Jeroen Mostert在评论中所述,从.NET Framework 4.6开始,Task.CompletedTask属性是公共的,所以你可以这样做:

virtual Task RunAsync()
{
  return Task.CompletedTask;
}

因此,如果你可以使用4.6+,这是最新,最干净的选择。当然,如果您需要任务实际返回值,Task.FromResult仍然存在:)