【问题标题】:Should I use async/await in my controller?我应该在控制器中使用 async/await 吗?
【发布时间】:2020-11-10 19:22:38
【问题描述】:

我在 youtube 上观看了 Les Jackson 的一些视频,介绍了如何创建 .net 核心 API。 Les 将这种方法用于他的控制器中的方法

    public ActionResult<IEnumerable<Command>> GetAllCommands()
    {
        var commandItems = _repository.GetAppCommands();
        return Ok(commandItems);
    }

但是我刚刚阅读了使用这种方法的书中的一篇文章

public async Task<ActionResult<IEnumerable<Data.CityDataClass>>> GetCities()
{
    return await _repository.GetCities();
}

在我看来,第二种方法是使用“异步”声明的过度杀伤力吗?第一种方法在得到结果之前不会返回任何东西。

谢谢

【问题讨论】:

  • "第一个方法在得到结果之前不会返回任何东西。"是的,但它会保持线程阻塞,直到结果准备好。在某些情况下,这不是问题 - 在其他情况下可能是。 (假设您的服务器负载很重,并且此方法需要一段时间......您是否希望每个未完成的调用都占用一个线程?)
  • 这能回答你的问题吗? How and when to use ‘async’ and ‘await’
  • “第二种方法是使用“async”声明的矫枉过正吗?”这取决于。如果您的方法是async,那么您必须等待它(除非它具有同步等效项)。如果您可以选择这两种方法,那么判断哪种方法更快的唯一真正方法就是对其进行测试。基本上,如果您有一个集中式服务,那么async/await 可以防止线程饥饿。如果您的服务没有受到这种影响,那么同步等效可能会更好,因为它避免了上下文切换的开销,但最终唯一的判断方法是对其进行负载测试。
  • 您可能对eliding async/await的优缺点感兴趣。

标签: c# async-await task-parallel-library


【解决方案1】:

如果您在I/O threads阅读这篇文章,您会更好地理解这一点

要正确使用 .NET 的异步和并行特性,您还应该了解 I/O 线程的概念。

并非程序中的所有内容都会消耗 CPU 时间。当线程试图从磁盘上的文件中读取数据或通过网络发送 TCP/IP 数据包时,它所做的唯一事情就是将实际工作委托给设备(磁盘或网络适配器)并等待结果。

I/O 线程是一种抽象,旨在将与设备的工作隐藏在一个简单而熟悉的概念后面。这里的要点是您不必以不同的方式使用这些设备,您可以将它们内部的管道视为通常的 CPU 消耗线程。同时,I/O 线程与 CPU 密集型线程相比非常便宜,因为实际上它们只是对设备的请求

因此,第一种方式不会使用 I/O 线程,而第二种方式则要便宜得多。

在您的情况下,访问数据库时,您实际上是在执行 I/O(网络)操作。通过使用异步编程,您可以在 I/O 线程上等待 I/O(数据库读取)操作完成,而不会阻塞线程。

编辑(根据利亚姆的评论)

另一个有趣的阅读是async in depth

在整个过程中,一个关键的要点是没有专门用于运行任务的线程。尽管工作是在某些上下文中执行的(也就是说,操作系统确实必须将数据传递给设备驱动程序并响应中断),但没有专门用于等待来自请求的数据返回的线程。这允许系统处理更多的工作,而不是等待一些 I/O 调用完成。

更多信息check the asynchronous overhead here

  1. 如果异步方法同步完成,则性能开销相当小。
  2. 如果异步方法同步完成,将发生以下内存开销:对于异步任务方法没有开销,对于异步任务方法,开销是每个操作 88 字节(在 x64 平台上)。
  3. ValueTask 可以消除上述同步完成的异步方法的开销。
  4. 如果方法同步完成,则基于 ValueTask 的异步方法比基于 Task 的方法快一点,否则慢一点。
  5. 等待未完成任务的异步方法的性能开销要大得多(x64 平台上每个操作约 300 字节)。

【讨论】:

  • OP 问题涉及的设备、磁盘或网络在哪里? GetAppCommandsGetCities 方法可以使用它们,但没有证据表明这种行为。请澄清这一点。
  • IO 线程是答案的一部分,但不是全部。 async/await 还释放了线程池线程,这有助于集中式服务的考虑,但也增加了上下文切换和状态机存储形式的开销。
  • 同意!我添加了一些更多信息供任何人检查开销(这是最小的)和一些深入的异步文章。
猜你喜欢
  • 1970-01-01
  • 2020-07-23
  • 2021-06-25
  • 2021-09-11
  • 1970-01-01
  • 2018-11-18
  • 2018-09-14
  • 2017-11-18
  • 1970-01-01
相关资源
最近更新 更多