我应该在ASP.NET Core API控制器中始终使用async/await吗



例如,我有一个ASP.NET Core API controller从服务中获取一些数据,2是实现控制器方法的可能方法:

带async/await:

[HttpGet]
public async Task<IActionResult> GetSomeDataAsync()
{
return await someService.GetSomeDataAsync();
}

无异步/等待:

[HttpGet]
public Task<IActionResult> GetSomeDataAsync()
{
return someService.GetSomeDataAsync();
}

这两个哪个更好?这里的关键是只有一个对另一个异步方法(someService.GetSomeDataAsync()(的调用。

根据ASP.NET团队的ASP.NET核心性能最佳实践:

避免阻止呼叫

ASP.NET核心应用程序应设计为同时处理多个请求。异步API允许一小部分线程池通过不等待阻塞调用来处理数千个并发请求。线程可以处理另一个请求,而不是等待长时间运行的同步任务完成。

ASP.NET核心应用程序中的一个常见性能问题是阻止可能是异步的调用。许多同步阻塞调用会导致线程池不足和响应时间降低。

  • 请使热代码路径异步
  • 如果有异步API可用,请异步调用数据访问、I/O和长时间运行的操作API
  • 不要使用Task.Run((使同步API异步
  • 请确保控制器/Razor页面操作异步。为了从异步/等待模式中获益,整个调用堆栈都是异步的

避免对HttpRequest/HttpResponse主体进行同步读取或写入

ASP.NET Core中的所有I/O都是异步的。服务器实现Stream接口,该接口同时具有同步和异步重载。应该优先选择异步线程,以避免阻塞线程池线程。阻塞线程可能导致线程池不足。

首选ReadFormAsync而不是Request.Form

使用HttpContext.Request.ReadFormAsync而不是HttpContext.Request.FormHttpContext.Request.Form可以在以下条件下安全地只读:

  • 调用ReadFormAsync读取了表单,并且
  • 正在使用HttpContext.Request.Form读取缓存的表单值

优化数据访问和I/O

与数据存储和其他远程服务的交互通常是ASP.NET Core应用程序中最慢的部分。高效地读取和写入数据对于良好的性能至关重要。

  • 请异步调用所有数据访问API

在"只做一件异步事情"的场景中,两者之间的差异是微妙的,主要围绕异常,特别是a:如果抛出异常而不是返回错误任务,会发生什么,以及b:任何异常场景中堆栈跟踪的详细信息。

事实上,在这里两者都可以,但我会保持简单,并在大多数应用程序代码中使用await语法(顶级web请求处理程序肯定是应用程序代码(。这里有一点机械开销,但在应用程序级别,这真的没什么,所以不用担心。

但是,如果您正在编写一个库函数,该函数每次请求(网络IO、字符串处理等(调用数百或数千次-,那么值得考虑更积极(更手动(的优化任务机制的方法。

很难绝对确定async-await是否有助于或阻碍您的控制器操作方法(因为您需要用不同的负载测试它(,但作为一般规则,任何访问数据库或文件系统或其他远程API的控制器都应该是异步的,并且执行简单的存储器内计算的控制器可以保持同步。异步调用会增加一点(但只是非常少(开销,因此,如果有疑问,请使用异步调用。

返回异步方法的最佳实践。。。异步。

这被称为异步,请参阅msdn指南:

https://learn.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming

最新更新