什么都不做的异步方法
本文关键字:异步方法 什么 | 更新日期: 2023-09-27 18:13:16
我有一个接口IAnimation
,它公开了一个方法BeginAsync()
。该方法应该启动动画并在动画完成时返回。
我想做的是实现一个null
动画类NoAnimation
,它只在执行BeginAsync()
时返回。
这是正确的实现吗?
public async Task BeginAsync()
{
await Task.Run(() => { });
}
我怀疑有一种比这更优雅的方法。我也考虑过创建一个空方法。但是这会给我一个警告,我也不喜欢。
使用Task.CompletedTask
返回一个已完成的任务:
public Task BeginAsync()
{
return Task.CompletedTask;
}
如果你有一个Task<TResult>
,使用Task.FromResult<TResult>
返回一个完成的任务,结果:
public Task<bool> BeginAsync()
{
return Task.FromResult(true);
}
您当前的实现非常低效,因为它构建状态机,并且还使用ThreadPool线程来运行空任务。
我明白这并没有完全回答最初的问题(或者至少不是在另一个答案中没有的方式)。它为@ReedCopsey的答案提供了额外的背景,对于那些人(包括我!)而其他人,根据对这个答案的评论)最初可能很难理解这里发生了什么。
很容易陷入这样的陷阱:认为async
必须是任何异步方法签名的一部分。看起来是这样;它(误导!)读起来好像它的全部目的是将一个方法标记为异步。
但它不是,Task
或Task<T>
是必需的,而不是async
。这在@ReedCopsey的答案和下面的正确示例(稍微改编自这个有用的SO答案)中显示:
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
关键字:一个"异步"方法本身,不管它是如何实现的,只是一个返回启动(可能已经完成)的Task
或Task<T>
的方法。
如果async
没有将方法标记为异步,它会做什么?这是一种更简单地编写异步方法的方法:一旦你把它应用到一个方法上,你可以使用await
关键字来告诉编译器正确地为你处理辅助异步调用,非常简单(没有它,你可以尝试手动处理辅助Task
,使用更多类似于上面代码块的代码,但这样做会非常复杂,容易出错)。
因此,如果您只是想从"异步"(即Task
返回)方法返回一个什么都不做,已经完成的任务,您可以并且应该同步(!),如在@ReedCopsey的答案中,使用Task.CompletedTask
或Task.FromResult(...)
。