ASP.NET 请求中的 async/await 有哪些好处?

Pro*_*rAl 0 c# performance async-await

当您知道自己已经位于单独的线程(即 ASP.NET Core 端点)内时,我试图了解使用 async/await C# 代码的性能优势。

假设我们在 ASP.NET Core API 中有以下 C# 代码:

//This is the ASP.NET Core endpoint
public async Task<ActionResult> Get()
{
      await CallAllAsync();
}

public async Task<ActionResult> CallAllAsync()
{
      await CallBAsync();
      await CallCAsync();
      await CallDAsync();
}

public async Task<ActionResult> CallBAsync()
{
      await SomeDatabaseCallAsync();
}
public async Task<ActionResult> CallCAsync()
{
      await SomeHttpCallAsync();
}
public async Task<ActionResult> CallDAsync()
{
      await SomeFileSaveAsync();
}
Run Code Online (Sandbox Code Playgroud)

我对上述工作原理的理解是:

  1. 当 HTTP 请求进入 ASP.NET Core 端点时,将从线程池中获取一个新线程并用于运行该调用的代码。我们称这个线程为Thread_Get
  2. 调用时,会从任务池中取出一个任务实例,并运行await CallAllAsync()其中的代码。CallAllAsync()假设该任务的线程是Thread_All。这会暂停父级,并且在完成Thread_Get之前不会运行。Thread_All
  3. 因为里面的调用CallAllAsync()是连续的(即不使用 )Task.WhenAll(),所以它们都会依次运行。所以这里也会发生同样的过程。从任务池中取出一个任务,代码CallBAsync()在其中运行,它使用另一个任务/线程来运行SomeDatabaseCallAsync()。一旦这些完成,同样的情况也会发生在CallCAsync()和 上CallDAsync()

我的问题是,由于所有这些都在该 ASP.NET Core 端点的新线程中运行,并且所有调用都是连续的,因此在此代码中使用 async/await 是否有任何性能优势?

Joh*_* Wu 5

当调用await CallAllAsync() 时,将从任务池中获取一个Task 实例,并运行CallAllAsync() 内的代码。假设该任务的线程是 Thread_All。这会暂停parentThread_Get,并且在Thread_All完成之前不会运行。

这是不正确的。当被调用时,它会同步执行,直到到达CallAllAsync()第一个。await此时Task创建了代表该方法的其余部分(“继续”)的(没有池)。然后任务返回给调用者。

我的问题是,由于所有这些都在该 ASP.NET Core 端点的新线程中运行,并且所有调用都是连续的,因此在此代码中使用 async/await 是否有任何性能优势?

当前的请求没有立即的好处,因为操作必须串行发生,并且每个操作都需要一定的时间才能完成。但是,使用这种async逻辑允许线程在等待这些异步任务完成时将其交给其他请求。这为您的整体应用程序提供了更好的吞吐量,从而有利于所有请求。