例如,我有一个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.Form
。HttpContext.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