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

Dav*_*vid 11 c# async-await

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

virtual async Task RunAsync()
Run Code Online (Sandbox Code Playgroud)

派生类应该使用类似的方式覆盖此实现

public override async Task RunAsync()
{
  await base.RunAsync();
  await this.DoSomethingElse();
}
Run Code Online (Sandbox Code Playgroud)

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

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

Lua*_*aan 16

你误解了它是如何async运作的.这不是签名的一部分,所以如果你没有需要await,你实际上并不使用它.因此,即使你提供一个Task RunAsync()方法,你可以只写它没有async,例如:

virtual Task RunAsync()
{
  return Task.FromResult(false);
}
Run Code Online (Sandbox Code Playgroud)

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

override async Task RunAsync()
{
  await base.RunAsync();
  await DoSomeOtherStuffAsync();
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:

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

virtual Task RunAsync()
{
  return Task.CompletedTask;
}
Run Code Online (Sandbox Code Playgroud)

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

  • @David:框架*提供了 - 它是[Task.CompletedTask](https://msdn.microsoft.com/library/vstudio/system.threading.tasks.task.completedtask). (4认同)
  • 当然,我现在看到的是非常非常近期的 - 从4.6开始.不过,迟到总比没有好.:-) (2认同)