【问题标题】:Asynchronous method that does nothing什么都不做的异步方法
【发布时间】:2013-05-07 17:09:55
【问题描述】:

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

我想做的是实现一个null动画类NoAnimation,它在执行BeginAsync()时才返回。

这是正确的实现方式吗?

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

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

【问题讨论】:

标签: c# .net asynchronous async-await task


【解决方案1】:

只需使用Task.CompletedTask 即可返回已完成的任务:

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

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

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

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

【讨论】:

  • 第一种方法应该是:await Task.CompletedTask;。第二种方法应该是return await Task.FromResult(true); 另外还需要异步密钥。请修复您的代码
  • @GianpieroCaretti 不,这绝对是个坏建议。在不需要时使用await 会增加零收益和额外开销。我所拥有的是正确的。
  • 需要注意的是,该属性仅在.net 4.6+中可用
  • 这个有一个单行吗?
  • @coolbreeze Task.CompletedTaskTask.FromResult 都已经是一个班轮了...?
【解决方案2】:

很容易陷入认为async 必须是任何异步方法签名的一部分的陷阱。看起来一定是;它(具有误导性!)读起来好像它的全部目的是将方法标记为异步。

但不是,TaskTask&lt;T&gt; 是必需的,但不是 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 关键字的原因:一个“异步”方法本身,不管它是如何实现的,只是 一种返回已启动(并且可能已经完成)TaskTask&lt;T&gt; 的方法。

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

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

【讨论】:

    猜你喜欢
    • 2022-12-18
    • 2010-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-13
    • 1970-01-01
    • 2011-02-18
    相关资源
    最近更新 更多