可以异步等待以增加执行时间的总时间

时间:2018-11-05 12:12:13

标签: c# asynchronous async-await

我的问题是与执行同步功能相比,执行异步功能所需的总时间。

我的理解如下:

-异步函数被调用

-执行代码,直到到达等待的代码

-等待代码被执行(例如读取数据库)时,执行线程被释放以执行其他任务

-等待的代码完成后,将分配一个线程来完成此调用

假设我说的是正确的,那么在繁忙的服务器上异步调用是否可能并且通常会比同步调用慢?

我的推理如下:

  1. 有一个异步开销(跟踪所有内容)

  2. 由于异步代码必须等待线程执行剩余的代码,因此它必须等待线程可用-因此,如果所有线程都忙,它将不得不等待一个? p>

如果这是真的,那么我认为这也意味着,如果有一个等待的方法没有执行任何I / O,它仍将释放执行线程并等待下一个线程可用以完成任务?

更新: 我知道await / async不会使响应时间更快,但是可以使服务器更高效。

我要澄清的要点是,由于异步任务完成时没有可用线程,例如,如果db调用已完成,是否需要等待,是否会使请求完成的时间更长?有更多时间使线程可用?我知道有很多方面需要等待,还有很多要考虑的地方,但是我只是想孤立地理解这一点。

更新2: 假设我有一个设计良好的异步系统,但是我有一种方法,我需要尽可能快且精简-我不希望有任何事情会影响此调用的执行时间。当然,在这种情况下,如果我使该方法异步并释放线程,则调用可能必须等待线程完成才能执行,而如果它是异步的,则该线程将始终在那里等待-在牺牲了其余应用程序的性能?

2 个答案:

答案 0 :(得分:3)

  
      
  1. 异步会有开销(跟踪所有内容)
  2.   

正确。但是,从异步任务获得的速度往往远远超过开销成本,因此可以忽略不计。除非您开始使用 tiny 执行主体对许多任务进行垃圾邮件处理,否则(每个任务)的开销将开始成为明显的因素。

  

我要澄清的要点是,由于异步任务完成时没有可用线程,例如,如果db调用已完成,是否需要等待,是否会使请求完成的时间更长?线程有更多时间可用?

就目前而言,这是正确的。由于等待任务完成而被搁置的“第一”操作将无法在任务完成的确切时间排成一行。

该操作将不得不重新加入队列,但确实比尚未启动的操作具有更高的优先级。这非常类似于例如邮局的工作方式:

  • 您排队
  • 您到达前台,邮政工作人员会给您填写一张表格(因此您会等待填写该表格”
  • 您走到一边并填写表格,然后邮政工作人员可以帮助他人而不是在等待您时空转。
  • 当您完成任务时,您不会将当前正在获得帮助的客户抛在一边……(这似乎是您想要的:立即吸引线程的注意力,而不是等待其当前完成的工作) 。
  • ...但是您将被允许在尚未与邮政人员交谈的人们面前排队。

注意:至少我的文化(西欧)是这样处理的。您的里程可能会有所不同。

因此,是的,您的假设实际上是正确的;但我确实要强调,与异步工作的收益相比,此处的时差在天文上可以忽略不计。
如果要挤压特定的操作以获得绝对最快的性能,则必须为其提供自己的线程,而不要让它参与“异步池”计划。但我强烈建议反对,因为这样做的好处将是极度边缘化,并且绝不会超过开发它的复杂性。

第二,请考虑在“精心设计的异步系统”(根据您的问题)中,任务将被分成最小的合理操作,因此单个任务的执行(不包括其间的任何等待时间)将不会有意义。在实践中,您不会注意到必须等待线程可用-除非您使服务器的工作负载大大超支并真正达到了极限-在这一点上,您还需要其他更大的鱼来炒。

  

假设我有一个设计合理的异步系统,但是我有一种方法需要尽可能的快速和精简-我不希望任何事情会妨碍此调用的执行时间。当然,在这种情况下,如果我使该方法异步并释放线程,则调用可能必须等待线程完成才能执行,而如果它是异步的,则该线程将始终在那里等待-在牺牲了其余应用程序的性能?

我不明白你在这里的理由。

如果在同步示例中假设“线程正在等待我”,则意味着该线程可用并且当前不忙。但是对于您的异步示例,您假设所有线程都处于忙碌状态,并且都不可用。

这些情况完全不同。如果异步应用程序中的所有线程都已饱和,则同步应用程序中的所有线程(一个或多个)也将繁忙。

异步的意图恰恰相反。如果线程当前正在忙碌但处于空闲状态,则在同步应用程序中,您将被迫等待并且无法使用该线程。但是,在异步应用程序中,等待线程将能够在当前处于空闲状态时开始处理您的请求,因为它正在等待另一个尚未完成的任务。

答案 1 :(得分:0)

new ContainerControlledLifetimeManager()更加注重响应性能。

在客户端UI中,(通常)在单个线程(UI线程)中管理UI。如果您阻止该线程,则UI被阻止。 async-await提供了一种机制,可以在UI线程之外启动任务,并在该任务完成后在UI线程上恢复执行。该任务可以是IO或CPU密集型的。主要目标是摆脱UI线程。

在服务器(ASP.NET)中,线程池受到限制,因此在执行IO时释放线程使应用程序能够处理更多请求。另一方面,将任务用于CPU密集型工作只会将一个线程池线程换为另一个线程。

所有这些都是额外的工作,很显然,这会占用更多资源(CPU周期和内存)。都是关于响应能力,而不是性能。