c#.net核心web API中使用异步方法的条件

c#.net核心web API中使用异步方法的条件,c#,async-await,C#,Async Await,我正在实现几个小型服务,每个服务都使用实体框架来存储某些(但很少)数据。它们也有相当多的业务逻辑,因此将它们彼此分离是有意义的 我当然知道异步方法和异步等待模式本身可以解决性能方面的许多问题,特别是在涉及任何I/O或cpu密集型操作时 我不确定是否要使用实体框架逻辑的异步方法(例如SaveChangesAsync或FirstOrDefaultAsync),因为除了“是否是I/O或CPU密集型”之外,我找不到“现在你做,现在你不做”的指标 我在研究这个主题时发现了什么(不限于此,但这些都说明了问题

我正在实现几个小型服务,每个服务都使用实体框架来存储某些(但很少)数据。它们也有相当多的业务逻辑,因此将它们彼此分离是有意义的

我当然知道异步方法和异步等待模式本身可以解决性能方面的许多问题,特别是在涉及任何I/O或cpu密集型操作时


我不确定是否要使用实体框架逻辑的异步方法(例如SaveChangesAsync或FirstOrDefaultAsync),因为除了“是否是I/O或CPU密集型”之外,我找不到“现在你做,现在你不做”的指标

我在研究这个主题时发现了什么(不限于此,但这些都说明了问题):

  • 不使用它会导致应用程序停止响应,因为线程(不是cpu的线程,而是操作系统的虚拟线程)可能会因为阻塞对数据库的i/o调用而耗尽

  • 使用它会使代码膨胀并降低性能,因为每个方法都有上下文切换。特别是当我将这些应用于实体框架调用时,这意味着对于从控制器到业务逻辑再到存储库再到数据库的一次调用,至少有三个上下文开关

我不知道的,这就是我想从你那里知道的:

  • 有多少虚拟操作系统线程?或者更准确地说:如果我希望我的应用程序和服务器能够在5秒内处理100个对此服务的请求(我不希望它们超过100个,100个已经过了测试),那么我应该放弃使用异步/等待吗

  • 对于我的任何服务,我可以通过哪些精确的指标来回答这个问题

  • 或者我应该始终使用异步方法进行I/O调用,因为它们已经存在,而且服务器上的负载情况随时可能发生变化,而且发生了很多事情,异步方法可以帮助我解决这些问题


TLDR:我应该使用异步吗?对!

在试图理解async/Wait时,您似乎犯了最常见的错误。异步与多线程是正交的

要回答您的问题,您应该在什么时候使用异步方法

If currentContext.IsAsync && method.HasAsyncVersion
    return UseAsync.Yes;
Else
    return UseAsync.No;
以上是简短的版本

Async/Await实际上解决了一些问题

  • 取消阻止UI线程
  • M:N线程
  • 多线程调度与同步
  • 基于中断/事件的异步调度
考虑到异步/等待有大量不同的用例,您陈述的“假设”仅适用于某些情况

例如,上下文切换仅在多线程情况下发生。基于单线程中断的异步实际上通过减少阻塞时间和保持操作系统线程良好的工作状态来减少上下文切换

最后,你关于操作系统线程的问题基本上是错误的

首先,每个操作系统线程都需要创建一个堆栈(4MB的连续RAM,100个线程意味着在完成任何工作之前有400MB的RAM)

其次,除非您的PC上有100个物理内核,否则您的CPU必须在每个OS线程之间进行上下文切换,从而导致CPU在加载该线程时暂停。通过使用M:N线程,您可以通过减少操作系统线程的数量而不是使用绿色线程(dotnet中的任务)来保持CPU的运行

第三,并非所有的“等待”结果都是“异步”行为。任务能够同步返回,短路所有的“膨胀”


简而言之,如果不深入挖掘,就很难通过从异步方法切换到同步方法来找到优化机会。

TLDR:我应该使用异步吗?对!

在试图理解async/Wait时,您似乎犯了最常见的错误。异步与多线程是正交的

要回答您的问题,您应该在什么时候使用异步方法

If currentContext.IsAsync && method.HasAsyncVersion
    return UseAsync.Yes;
Else
    return UseAsync.No;
以上是简短的版本

Async/Await实际上解决了一些问题

  • 取消阻止UI线程
  • M:N线程
  • 多线程调度与同步
  • 基于中断/事件的异步调度
考虑到异步/等待有大量不同的用例,您陈述的“假设”仅适用于某些情况

例如,上下文切换仅在多线程情况下发生。基于单线程中断的异步实际上通过减少阻塞时间和保持操作系统线程良好的工作状态来减少上下文切换

最后,你关于操作系统线程的问题基本上是错误的

首先,每个操作系统线程都需要创建一个堆栈(4MB的连续RAM,100个线程意味着在完成任何工作之前有400MB的RAM)

其次,除非您的PC上有100个物理内核,否则您的CPU必须在每个OS线程之间进行上下文切换,从而导致CPU在加载该线程时暂停。通过使用M:N线程,您可以通过减少操作系统线程的数量而不是使用绿色线程(dotnet中的任务)来保持CPU的运行

第三,并非所有的“等待”结果都是“异步”行为。任务能够同步返回,短路所有的“膨胀”

简而言之,如果不深入挖掘,就很难通过从异步方法切换到同步方法来找到优化机会

我当然知道异步方法和异步等待模式本身可以解决性能方面的许多问题,特别是在涉及任何I/O或cpu密集型操作时

有点。异步代码的主要好处是它释放了线程。UI应用程序(即桌面/移动)在响应速度更快的用户界面中体现了这一优势。您正在编写的服务以更好的可伸缩性体现了这一优势——只有在负载下才能看到性能优势。此外,服务仅针对