使用异步等待是否可以避免线程耗尽? [英] Does Using Async Await Avoid Thread Exhaustion?
问题描述
我们正在对 .NET Core API
终结点上的以下性能问题进行故障排除:
We are troubleshooting the following performance issues on a .NET Core API
endpoint:
- 端点在较小负载下持续返回的时间少于
500MS
. - 当我们通过3个浏览器访问端点时,每秒发出一个请求,它会变慢(在添加第三个浏览器进行通话的一分钟内,响应时间下降到
50,000MS
或更糟. - 每个其他浏览器添加API使用的线程,例如基本线程数为40,第二个浏览器命中端点将导致52个线程,第三个峰值为70,依此类推.
- 加载一个端点后,整个API会缓慢返回(所有端点).这是我与#3"一起思考线程耗尽"的主要原因.
- The endpoint consistently returns in less than
500MS
under minor load. - When we hit the endpoint from 3 browsers, with one request a second, it gets progressively slower (within a minute of adding a third browser making calls, response times drops to
50,000MS
or worse. - Each additional browser adds threads used by the API, e.g. 40 threads base, 2nd browser hitting endpoint leads to 52 threads, third spikes to 70, and so on.
- When one endpoint is loaded, the entire API returns slowly (all endpoints). This is my main reason for thinking "thread exhaustion", along with point #3.
当前代码如下:
public IActionResult GetPresentationByEvent(int eventid)
{
return Authorized(authDto =>
{
var eventList = _eventService.GetPresentationByEvent(eventid);
return Ok(eventList)
})
}
我的理论是 return Authorized(authDto =>
会保留一个线程,直到返回为止,这会导致线程耗尽.
My theory is that return Authorized(authDto =>
holds a thread until it returns, leading to thread exhaustion.
public async Task<IActionResult> GetPresentationByEvent(int eventid)
{
return Authorized(async authDto =>
{
Task<List<whatever>> eventList = _eventService.GetPresentationByEvent(eventid);
return Ok(eventList)
}
}
Authorized
是第三方库的一部分,所以我很难对此进行测试.想知道这是否是一个可能的问题/解决方案.
Authorized
is part of a third-party library, so I can't test this easily. Would like to know if this looks like a likely problem/solution.
推荐答案
是的,异步等待可以减少线程耗尽.简而言之,当您生成的任务超出ThreadPool的处理能力时,就会出现线程耗尽.
Yes async await can reduce thread exhaustion. In a few words thread exhaustion arise when you generate more tasks than your ThreadPool can handle.
There are subtle specifities that you can check here : Thread starvation and queuing
唯一需要牢记的是,您永远都不应阻塞任务内部.这意味着在异步等待状态下调用异步代码(并且永远不要在未完成的任务上使用.Wait或.Result).
The only thing that you have to keep in mind on your side is that you should never block inside a task. This implies calling asynchronous code with async await (and never using .Wait or .Result on a non finished task).
如果使用的阻塞代码未使用异步等待模式,则必须在专用线程(而不是任务线程队列)上生成它.
If you use some blocking code wich is not using the async await pattern you have to spawn it on a dedicated thread (not the task thread queue).
这篇关于使用异步等待是否可以避免线程耗尽?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!