我有一个接口IAnimation
,它公开了一个方法BeginAsync()
。该方法应该在开始动画时返回并在完成时结束。
我想要做的是实现一个null
动画类NoAnimation
,当它执行BeginAsync()
时,它只会返回。
这是否是正确的实现?
public async Task BeginAsync()
{
await Task.Run(() => { });
}
我觉得有比这个更优雅的方法。我也考虑过创建一个空方法,但是那样会给我一个我不喜欢的警告。
我有一个接口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);
}
您当前的实现非常低效,因为它会构建状态机,并使用线程池线程来运行空任务。
await Task.CompletedTask;
。第二个方法应该是 return await Task.FromResult(true);
此外,它们需要使用 async 关键字。请修复您的代码。 - GianpieroTask.CompletedTask
和 Task.FromResult
都已经是一行代码了,是吗? - Reed Copsey我知道这并不完全回答原始问题(或者至少不是以一种其他答案没有的方式)。它为@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
的)方法返回一个无操作的已完成任务,你可以并且应该同步地这样做,就像@ReedCopsey的回答中使用Task.CompletedTask
或Task.FromResult(...)
一样。