27

我有一个IAnimation公开方法的接口BeginAsync()。该方法应该启动动画并在完成后返回。

我想做的是实现一个只在执行时返回的null动画类。NoAnimationBeginAsync()

这是正确的实施吗?

public async Task BeginAsync()
{
    await Task.Run(() => { });
}

我怀疑有比这更优雅的方法。我还考虑过创建一个空方法。但这给了我一个我也不喜欢的警告。

4

2 回答 2

53

只需用于Task.CompletedTask返回已完成的任务:

public Task BeginAsync()
{
     return Task.CompletedTask;
}

如果您有Task<TResult>用于Task.FromResult<TResult>返回已完成任务的结果:

public Task<bool> BeginAsync()
{
     return Task.FromResult(true);
}

您当前的实现效率非常低,因为它构建了状态机,并且还使用 ThreadPool 线程来运行空任务。

于 2013-05-13T15:41:23.193 回答
2

很容易陷入思维的陷阱,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关键字:一个“异步”方法本身,不管它是如何实现的,它只是一个返回启动的方法(并且可能已经完成)TaskTask<T>

如果async不将方法标记为异步,它会做什么?这是一种更简单的写异步方法的方法:一旦你把它应用到一个方法上,你可以使用await关键字告诉编译器为你正确处理辅助异步调用(没有它,你可以尝试Task手动处理辅助异步调用) ,在上面的代码块中使用更多类似的代码,但这样做会非常复杂且容易出错)。

因此,如果您只想从“异步”(即Task-returning)方法返回一个无所事事的、已经完成的任务,您可以并且应该同步(!)这样做,就像在@ReedCopsey 的答案中一样,使用Task.CompletedTaskor Task.FromResult(...)

于 2020-08-20T17:39:58.993 回答