【问题标题】:Call chain for async/await ... await the awaitable or return the awaitable?async/await 的调用链......等待可等待的还是返回可等待的?
【发布时间】:2024-04-23 23:30:01
【问题描述】:

给定一个异步方法:

public async Task<int> InnerAsync()
{
    await Task.Delay(1000);
    return 123;
}

通过中间方法调用,中间方法是等待异步方法IntermediateA还是仅仅返回TaskIntermediateB

public async Task<int> IntermediateA()
{
    return await InnerAsync();
}

private Task<int> IntermediateB()
{
    return InnerAsync();
}

据我所知,调试器似乎两者的工作方式完全相同,但在我看来,IntermediateB 应该通过避免在状态机中再输入一个 await 来获得更好的性能。

是吗?

【问题讨论】:

  • 区别在于异常处理。为了更好地理解这一点,我建议你尝试从内部函数中抛出一个异常,看看事情是如何工作的。
  • 谢谢。我根本没有考虑异常处理。
  • “在我看来 IntermediateB 应该表现更好” - 是的,但差异将是几纳秒。它还可以在生成的二进制文件中节省几十个字节。
  • 我建议你阅读Eliding Async and Await

标签: c# asynchronous async-await


【解决方案1】:

这两种方法存在细微差别。如果你 await 失败的任务,异常将在该方法中抛出,但如果你通过任务认为该方法然后 await 它,异常将在消费者方法中抛出。另一个差异更为罕见,如果消费者等待任务并且如果它发生延迟,则可以在等待点完成任务并绕过状态机。

【讨论】:

  • 谢谢。我根本没有考虑异常处理。
  • 性能怎么样?这不是创建两个状态机(等待内部)吗?
  • 如果没有 try/catch,异常将传播给调用者。你能指出一个实质性的实际差异吗?
最近更新 更多