C#:后台工作/通信的设计模式,不滥用Task.Run
Posted
技术标签:
【中文标题】C#:后台工作/通信的设计模式,不滥用Task.Run【英文标题】:C#: design pattern for background work / communication without abusing Task.Run 【发布时间】:2020-06-01 11:09:27 【问题描述】:我有一个 c# .net (4.7.2) rest api web 应用程序,它需要定期与最多 100 个设备进行通信 (http)。
目前我们基本上有一个事件处理程序,它最初为每个设备创建一个Task.Run
(包含通信工作*)。在每个这样的Task.Run
结束时,将触发一个事件,以便再次触发该事件处理程序。因此,当拥有 100 台设备时,我们有大约 100 个短暂的“后台工作线程”正在运行,它们全部死亡并在大约 3 秒的时间段内再次导致 Task.Run
。
事实证明,这似乎非常昂贵——事实上,我怀疑这种架构有时会导致严重的问题,如“冻结”。
我知道这不是最佳做法,而且调用 Task.Run
不是免费的,而是旋转起来
定期最多 100 个线程应该不是什么大问题 - 至少我是这么认为的。
我不在乎线程池中排队的任务是否由于任务管理而延迟了一点。
所以我想知道哪种架构适合主要由“异步”代码组成的动态增长/收缩的后台工作负载。
尽管遵循了最佳实践 - 这种Task.Run
/ Eventhandler
方法真的有一个大坑吗?
*主要工作包括建立一个http连接并等待它的结果。最后必须完成数据库读/写。所以它可以通过使用异步代码来完成。
【问题讨论】:
许多好的问题会根据专家的经验产生一定程度的意见,但这个问题的答案往往几乎完全基于意见,而不是事实、参考资料或特定专业知识。 我已经用谷歌搜索过那个,但它似乎是为 windows 表单应用程序设计的 这将有助于编辑您的帖子以包含您当时正在使用的内容;你提到web app
好的,用什么?
同意 - 已更新。
我会考虑使用 await 等来启动所有 100 个请求,而不需要每个请求一个线程。
【参考方案1】:
我建议您使用 Hangfire 连续执行此操作。您可以通过 API 访问您的设备,并与所有设备和您的主要设备进行手动连接。
它可以向您显示活动和线程的报告和状态,您可以对其进行编程。我发现它比运行线程更可靠和稳定!
另一方面,您可以在子应用程序中使用“观察者设计模式”。当时间或事件触发时,您代码中的所有订阅者都可以触发并回答您。
您可以在这里阅读更多内容:
Observer Design Pattern
【讨论】:
【参考方案2】:对于您描述的问题非常适合Durable Task Freamork。 从包装盒中,您将拥有:
-
可扩展(由于 DTF 使用 ServiceBus 的架构,每个实例都可以处理工作)
你可以控制执行
提供了配置并行级别的可能性
对于长时间运行的处理,您可以使用 Azure Durable Function。
【讨论】:
以上是关于C#:后台工作/通信的设计模式,不滥用Task.Run的主要内容,如果未能解决你的问题,请参考以下文章