async不需要等待的任务方法

jch*_*tof 3 c# async-await

我有一组从基类继承的命令.基类具有以下声明:

public virtual async Task Execute(object parameter){}
Run Code Online (Sandbox Code Playgroud)

继承类提供了此方法的重写,并非所有类都等待任务.在这些情况下,编译器会生成警告:

这种异步方法缺少"等待"运算符并将同步运行.考虑使用'await'运算符等待非阻塞API调用,或'await Task.Run(...)'在后台线程上执行CPU绑定工作.

明确提供任务完整返回值是否正确?

public override async Task Execute(object parameter) {
    //code containing no await statements...
    await Task.CompletedTask;
}
Run Code Online (Sandbox Code Playgroud)

Fed*_*uma 8

你应该避免async在重写方法中使用关键字await,而不是在任何东西上,而只是返回Task.CompletedTask:

public override Task Execute(object parameter) {
    //code containing no await statements...
    return Task.CompletedTask; // or Task.FromResult(0) for older .NET versions
}
Run Code Online (Sandbox Code Playgroud)

这是的(少数)的用例这样的"嘲笑"的任务之一,因为你可以通过了解看这个问题有关Task.FromResult.这些考虑仍然有效Task.CompletedTask.

  • 我将原始代码的输出和dotPeek推荐更改的输出区分开来,它们是相同的(调试dll).您的示例也删除了编译器警告,这是我最初的动机.- 谢谢! (2认同)

Ste*_*ary 5

As a counterpoint, there is a difference in the way exceptions are handled.

If an exception is raised from the synchronous code in the non-async version, then that exception is raised directly to the caller (very unusual for methods with asynchronous signatures).

If an exception is raised from the synchronous code in the async version, then that exception is captured and placed on the returned task (which is the expected behavior for methods with asynchronous signatures).

So, if the method is called as such, the different implementations would have different exception semantics:

var task = Execute(parameter); // non-async exceptions raised here
...
await task; // async exceptions raised here
Run Code Online (Sandbox Code Playgroud)

Most of the time, though, the method is called and immediately awaited, so those two semantics merge together:

await Execute(parameter); // both async and non-async exceptions raised here
Run Code Online (Sandbox Code Playgroud)

It probably won't matter, but I believe it's an important distinction to be aware of.

If the exception semantics are important to you, then you do want to use async to generate a state machine around your synchronous code, and you can disable the warning in your code:

#pragma warning disable 1998 // use async keyword to capture exceptions
public override async Task Execute(object parameter) {
#pragma warning restore 1998
  //code containing no await statements...
}
Run Code Online (Sandbox Code Playgroud)