c# - 我应该将 Task.Run() 用于执行 I/O 的 BackgroundService
问题描述
我有一个需要执行一些后台任务的 ASP.NET Core 5 API。这些后台任务将在整个应用程序生命周期中运行,并且将读取 azure 队列,因此花费大量时间无所事事。
我已经读过 I/O 你不应该使用 Task.Run() 因为它效率低下,但如果在我的情况下我没有等待 I/O 调用,我正在等待发生的后台任务做很多 I/O 调用,可以吗?似乎如果我不使用 Task.Run() ,那么每次我的后台任务从队列中获取一些东西,所以等待之后的代码继续,那么它将阻塞 ASP 中的一些主线程,这些主线程在第一个后台处理任务地方。
解决方案
这些后台任务将在整个应用程序生命周期中运行,并且将读取 azure 队列,因此花费大量时间无所事事。
我同意其他人的评论:到目前为止,最好的解决方案是将这些完全移出 ASP.NET 进程。例如,Azure Functions 具有对 Azure 存储队列的内置支持。Azure Functions 在进程内通过 ASP.NET 的优势包括:
- 您的 API (ASP.NET) 可以独立于后端 (Azure Function) 进行扩展。
- 后端缩放是自动的。随心所欲地上升,可能下降到零。
- 后端进程有自己的线程池,因此不会干扰 ASP.NET 线程池。
我已经读过 I/O 你不应该使用 Task.Run() 因为它效率低下
Task.Run
应该避免在 ASP.NET 的请求处理管道中。无论正在完成的工作类型如何,它总是效率低下。
Task.Run
对于 ASP.NET 进程中的后台任务可能很有用,尤其是在后台任务启动期间完成了阻塞工作的情况下。
ASP.NET的主要内容Task.Run
是您不想干扰 ASP.NET 线程池启发式。定期将工作排队到线程池是一个问题,因为您正在窃取线程然后定期重新注入它们。因此,Task.Run
在处理每个 HTTP 请求或处理每个队列项时使用将是一个坏主意。在启动时完成一次Task.Run
并不重要。
似乎如果我不使用 Task.Run() 那么每次我的后台任务从队列中获取一些东西,所以等待之后的代码继续,那么它将阻塞 ASP 中的一些主线程,这些主线程在第一个后台处理任务地方。
如果在您的消息处理期间正在进行阻塞工作,这是一个有效的问题。
考虑async
/await
的一种方法是,每种方法都被分解成片段(在每个await
点),并且每个片段都单独安排,一次一个。每次调度一个片段时,它会占用一个线程池线程,运行该片段,然后返回该线程。只要工作速度快,这很好,但如果其中一个有阻塞工作,那么 ASP.NET 线程池启发式可能会受到影响。
推荐阅读
- intershop - DBInit ChannelPreparer 故障
- javascript - Highcharts 导出服务器 - 获取空白图表
- angular - 在 Angular 8 项目中使用对象哈希会导致“无法读取未定义的属性‘加密’”错误
- cucumber - 小黄瓜场景大纲或多个场景?
- python - 通过 matplotlib 图表绘制 pandas 数据框并在图表上绘制点
- python - Pandas:用列中“n”个最接近的非空值的平均值替换 NaN
- javascript - 打印窗口打开时,我的 Angular 应用程序冻结
- html - Angular Bootstrap Datepicker 给了我们日期对象。我想要它作为日期
- android - 改造拦截器未将查询参数添加到 URL
- angular - Angular - 无法读取 null 的属性“排序”