我应该总是在 ASP.NET Core API 控制器中使用 async/await

Eri*_*ric 8 c# async-await asp.net-core

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

使用异步/等待:

[HttpGet]
public async Task<IActionResult> GetSomeDataAsync()
{
   return await someService.GetSomeDataAsync();
}
Run Code Online (Sandbox Code Playgroud)

没有异步/等待:

[HttpGet]
public Task<IActionResult> GetSomeDataAsync()
{
   return someService.GetSomeDataAsync();
}
Run Code Online (Sandbox Code Playgroud)

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

Moh*_*our 11

根据ASP.NET 团队的ASP.NET Core 性能最佳实践

避免阻塞呼叫

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

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

  • 使热代码路径异步。
  • 如果异步 API 可用,则异步调用数据访问、I/O 和长时间运行的操作 API。不要使用 Task.Run 使同步 API 异步。
  • 使控制器/剃刀页面操作异步。整个调用堆栈是异步的,以便从 async/await 模式中受益。

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

ASP.NET Core 中的所有 I/O 都是异步的。服务器实现 Stream 接口,该接口具有同步和异步重载。应该首选异步的,以避免阻塞线程池线程。阻塞线程会导致线程池饥饿。

比 Request.Form 更喜欢 ReadFormAsync

使用 HttpContext.Request.ReadFormAsync 而不是 HttpContext.Request.Form。HttpContext.Request.Form 只能在以下条件下安全读取:

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

优化数据访问和 I/O

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

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


Mar*_*ell 5

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

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

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


som*_*men -1

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

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

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

  • 我不认为“一路异步”意味着你所认为的意思。仅仅通过省略“async”和“await”关键字并不会突然不再使这个异步。它仍然返回一个等待的任务。现在我必须承认我并不完全确定,但我认为这里添加的所有异步都是在幕后添加另一个(不需要的)状态机。现在您可以说“是的,但最好将 async 关键字显式添加到所有异步方法中”。这当然是一个有效的想法,但只是个人喜好。 (3认同)