如何在另一个线程/任务中正确调用大逻辑?
Posted
技术标签:
【中文标题】如何在另一个线程/任务中正确调用大逻辑?【英文标题】:How to correctly invoke big logic in another Thread/Task? 【发布时间】:2018-07-07 08:23:05 【问题描述】:这是我的问题,我有一个 WCF 项目,实际上这并不重要,因为我相信它更多的是关于 C#/.NET。在我的 WCF 服务中,当客户端请求其中一种方法时,我对输入进行验证,如果成功,我将开始一些业务逻辑计算。我想在另一个线程/任务中启动这个逻辑,所以在输入验证之后我可以立即返回响应。它是这样的:
XXXX MyMethod(MyArgument arg)
var validation = _validator.Validate(arg);
if (validation.Succeed)
Task.Run(() => businessLogic())
return MyResponseModel();
我需要这样做,因为我的 buesinessLogic 最终可能需要很长时间的计算和数据库保存,但是请求服务的客户端必须立即知道模型是否正确。
在将在后台线程中运行的 businessLogic 计算/保存中,如果出现故障,我必须捕获异常并将其保存在数据库中。 (它的逻辑非常大,可以抛出很多异常,例如在计算后我将对象持久保存在数据库中,因此如果数据库处于脱机状态,则可能会抛出保存错误)
如何正确实施/使用什么来满足此类要求?我只是在考虑使用 Task.Run 并调用动作事件中的所有逻辑是否是一种好习惯?
【问题讨论】:
Task.Run 通常是错误的方法,它不会扩展。调查threading in ASP.NET 或使用(Azure)消息队列。 【参考方案1】:你可以这样做。
但请注意,工作进程可以随时退出。在这种情况下,出色的工作将完全丢失。也许您应该将工作排队到消息队列中。
此外,如果任务“崩溃”,您将不会收到任何通知。实现您自己的错误日志记录。
此外,您可以像这样生成的任务数量没有限制。如果处理太慢,就会有越来越多的工作排队。如果您知道服务器不会超载,这可能根本不是问题。
建议Task.Run
将使用线程,因此不能扩展。不一定如此。通常,任何处理的瓶颈不是线程数,而是正在使用的后端资源(数据库、磁盘、服务……)。即使使用数百个线程也不可能成为瓶颈。异步 IO 不是解决后端资源限制的方法。
【讨论】:
您没有考虑到 WCF 是一个 (ASP.NET) 服务,这会干扰线程管理等。但是您认为它不可靠是对的。以上是关于如何在另一个线程/任务中正确调用大逻辑?的主要内容,如果未能解决你的问题,请参考以下文章
正确关闭线程池:shutdown 和 shutdownNow 的区别