如何在另一个线程/任务中正确调用大逻辑?

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 的区别

任务在另一个线程 .NET 上异步运行

如何在另一个类中调用一个类的 main() 方法?

如何防止方法跨多个线程运行?

C ++如何等待在另一个线程上执行的方法然后主线程完成(VS2010)

如何正确停止线程