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的主要内容,如果未能解决你的问题,请参考以下文章

使用c#在两个进程之间进行通信

C#的dynamic使用中有啥需要注意的地方,以免滥用

C# 接口隐式提升类似于拆箱,使用已知的接口分层模式:

Chrome 扩展后台脚本如何与网页服务工作者通信?

Chrome扩展程序后台脚本如何与网页服务工作者进行通信?

急急急! c# winform开发模式窗体的一个问题