C# 使用异步等待是否可以避免线程耗尽?
我们正在对C# 使用异步等待是否可以避免线程耗尽?,c#,multithreading,asp.net-core-2.1,non-exhaustive-patterns,C#,Multithreading,Asp.net Core 2.1,Non Exhaustive Patterns,我们正在对.NET Core API端点上的以下性能问题进行故障排除: 在较小负载下,端点始终在小于500MS的时间内返回 当我们从3个浏览器点击端点时,每秒一个请求,会逐渐变慢(在添加第三个浏览器进行调用的一分钟内,响应时间会下降到50000ms,甚至更糟 每个附加浏览器都会添加API使用的线程,例如,基本线程数为40个,第二个浏览器命中端点会导致52个线程,第三个峰值会导致70个线程,依此类推 当加载一个端点时,整个API都会缓慢返回(所有端点)。这是我考虑“线程耗尽”以及第3点的主要原因
.NET Core API
端点上的以下性能问题进行故障排除:
500MS的时间内返回
50000ms
,甚至更糟 public IActionResult GetPresentationByEvent(int eventid)
{
return Authorized(authDto =>
{
var eventList = _eventService.GetPresentationByEvent(eventid);
return Ok(eventList)
})
}
我的理论是returnauthorized(authDto=>
会一直保持线程直到它返回,从而导致线程耗尽
public async Task<IActionResult> GetPresentationByEvent(int eventid)
{
return Authorized(async authDto =>
{
Task<List<whatever>> eventList = _eventService.GetPresentationByEvent(eventid);
return Ok(eventList)
}
}
公共异步任务GetPresentationByEvent(int-eventid)
{
返回已授权(异步身份验证=>
{
任务eventList=\u eventService.GetPresentationByEvent(eventid);
返回Ok(事件列表)
}
}
Authorized
是第三方库的一部分,因此我无法轻松测试。我想知道这是否是一个可能的问题/解决方案。是的,异步等待可以减少线程耗尽。简单地说,当生成的任务超过线程池的处理能力时,线程耗尽就会出现
您可以在此处查看一些细微的规范:
您需要记住的唯一一件事是,您永远不应该在任务内部阻塞。这意味着使用异步等待调用异步代码(并且永远不要在未完成的任务上使用.Wait或.Result)
如果您使用的某些块代码没有使用异步等待模式,则必须在专用线程(而不是任务线程队列)上生成它。是的,异步等待可以减少线程耗尽。简单地说,当生成的任务超过线程池所能处理的数量时,就会出现线程耗尽 您可以在此处查看一些细微的规范: 您需要记住的唯一一件事是,您永远不应该在任务内部阻塞。这意味着使用异步等待调用异步代码(并且永远不要在未完成的任务上使用.Wait或.Result) 如果您使用的某些块代码没有使用异步等待模式,则必须在专用线程(而不是任务线程队列)上生成它 我的理论是,return Authorized(authDto=>会一直保存线程,直到它返回,从而导致线程耗尽
public async Task<IActionResult> GetPresentationByEvent(int eventid)
{
return Authorized(async authDto =>
{
Task<List<whatever>> eventList = _eventService.GetPresentationByEvent(eventid);
return Ok(eventList)
}
}
是的。通过查看方法的返回值,可以很容易地判断方法是否同步。IActionResult
不是可等待的类型,因此此方法将同步运行
授权是第三方库的一部分,因此我无法轻松测试。想知道这是否可能是一个问题/解决方案
可能。这完全取决于授权的是否可以处理异步委托。如果可以,那么类似的操作将起作用:
public async Task<IActionResult> GetPresentationByEvent(int eventid)
{
return Authorized(async authDto =>
{
Task<List<whatever>> eventList = _eventService.GetPresentationByEventAsync(eventid);
return Ok(await eventList);
});
}
公共异步任务GetPresentationByEvent(int-eventid)
{
返回已授权(异步身份验证=>
{
任务eventList=\u eventService.GetPresentationByEventAsync(eventid);
返回Ok(等待事件列表);
});
}
注:
任务在传递给Ok
或其他助手之前,应等待
这引入了GetPresentationByEventAsync
,假设您的数据访问代码可以是异步的
由于使GetPresentationByEvent
异步可能需要一些工作,因此在尝试此操作之前,有必要研究Authorized
是否可以接受异步委托
使用异步等待是否可以避免线程耗尽
是和否。异步代码(包括异步
/等待
)使用更少的线程,因为它可以避免阻塞线程。但是,仍然有一个限制。线程耗尽仍然是可能的,因为异步代码需要一个空闲线程来完成。使用异步代码,通常在遇到诸如线程耗尽之类的可伸缩性问题之前,您可以获得一到两个数量级的可伸缩性。
public async Task<IActionResult> GetPresentationByEvent(int eventid)
{
return Authorized(async authDto =>
{
Task<List<whatever>> eventList = _eventService.GetPresentationByEvent(eventid);
return Ok(eventList)
}
}
有关async
ASP.NET的更多概念信息,请参阅
我的理论是,return Authorized(authDto=>会一直保存线程,直到它返回,从而导致线程耗尽
public async Task<IActionResult> GetPresentationByEvent(int eventid)
{
return Authorized(async authDto =>
{
Task<List<whatever>> eventList = _eventService.GetPresentationByEvent(eventid);
return Ok(eventList)
}
}
是的。通过查看方法的返回值,可以很容易地判断方法是否同步。IActionResult
不是可等待的类型,因此此方法将同步运行
授权是第三方库的一部分,因此我无法轻松测试。想知道这是否可能是一个问题/解决方案
可能。这完全取决于授权的是否可以处理异步委托。如果可以,那么类似的操作将起作用:
public async Task<IActionResult> GetPresentationByEvent(int eventid)
{
return Authorized(async authDto =>
{
Task<List<whatever>> eventList = _eventService.GetPresentationByEventAsync(eventid);
return Ok(await eventList);
});
}
公共异步任务GetPresentationByEvent(int-eventid)
{
返回已授权(异步身份验证=>
{
任务eventList=\u eventService.GetPresentationByEventAsync(eventid);
返回Ok(等待事件列表);
});
}
注:
任务在传递给Ok
或其他助手之前,应等待
这引入了GetPresentationByEventAsync
,假设您的数据访问代码可以是异步的
由于使GetPresentationByEvent
异步可能需要一些工作,因此在尝试此操作之前,有必要研究Authorized
是否可以接受异步委托
使用异步等待是否可以避免线程耗尽
是和否。异步代码(包括async
/await
)使用更少的线程,因为它可以避免阻塞线程。但是,仍然有一个限制。由于