我有一个接口IAnimation
,它公开了一个方法BeginAsync()
。该方法应该启动动画并在完成时返回。
我想要做的是实现一个null
动画类NoAnimation
,它只在执行BeginAsync()
时返回。
这是正确的实施吗?
public async Task BeginAsync()
{
await Task.Run(() => { });
}
我怀疑有一种比这更优雅的方法。我也考虑过了 创建一个空方法。但这给了我一个我不喜欢的警告。
答案 0 :(得分:19)
只需使用Task.CompletedTask
即可返回已完成的任务:
public Task BeginAsync()
{
return Task.CompletedTask;
}
如果您使用Task<TResult>
使用Task.FromResult<TResult>
来返回已完成的任务,结果为:
public Task<bool> BeginAsync()
{
return Task.FromResult(true);
}
您当前的实现效率非常低,因为它构建状态机,并且还使用ThreadPool线程来运行空任务。
答案 1 :(得分:1)
很容易陷入async
必须是任何异步方法签名的一部分的陷阱。看起来一定是;它(误导!)读取的目的似乎是将一个方法标记为异步。
但这不是必需的,Task
或Task<T>
是必需的,但async
不是必需的。这在@ReedCopsey的答案和以下示例中(从this useful SO answer略作改编)中可以看出:
public Task<int> MethodTaskAsync(int arg0, int arg1)
{
Task<int> task = new Task<int>(() => Method(arg0, arg1));
task.Start(); // Hot task (started task) should always be returned.
return task;
}
这就是为什么接口方法签名不需要且不能拥有async
关键字的原因:“异步”方法本身就是 just < / em>一种返回开始(并且可能已经完成)的Task
或Task<T>
的方法。
如果async
没有将方法标记为异步方法,它会做什么?这是一种更简单地编写异步方法的方法:将异步方法应用于方法后,可以使用await
关键字来告诉编译器非常简单地正确地为您处理辅助异步调用(没有它,您可以尝试使用上面的代码块中的更多代码来手动处理辅助Task
,但是这样做会非常复杂且容易出错。
因此,如果您只想从“异步”(即Task
-返回)方法中返回已完成的不做事的任务,则可以并且应该同步(!),如@ ReedCopsey使用Task.CompletedTask
或Task.FromResult(...)
的答案。