首页 > 解决方案 > 通过 REST 请求启动超长时间运行的进程

问题描述

我在一家自动化公司工作,所以我们为工业自动化创建流程。以前这种自动化是在机器方面完成的,但我们正在慢慢过渡到使用 c# 控制机器。

在我目前的项目中,一天的制作大约需要 2 个小时。工厂的操作员有一个我们在 c# 中使用 asp.net core MVC 创建的 Web 界面,他们可以在其中启动/暂停/停止此生产过程。

在启动过程时,我们在控制器中等待一个函数,该函数基本上是一个 while 循环,用于控制这个长达 2 小时的生产过程。

现在的问题是,当我发出 REST 请求以开始生产时,此请求需要 2 小时才能完成,我希望此请求立即完成,并且生产过程在我的 asp.net 核心应用程序的后台开始。

首先,我认为我可以省略等待,只需在我的控制器中执行此操作(简化代码):

_ = _productionController.StartLongProcess(); // This contains the while loop
return Ok();

但是由于 _productionController 是作用域的,并且它的所有依赖项也是如此,所以当方法返回时,它们会立即被处理掉,例如,我不能再访问我的数据库了。

该过程应该能够不断地与我们的数据库对话,以保存有关生产过程的信息,以防万一出现故障,这样我们就可以始终从中断的地方继续。

我现在向您提出的问题是,我们是否以错误的方式解决这个问题?我想在 asp.net 控制器中启动这些长时间运行的进程是不好的做法。

即使 REST 请求已经结束,如何确保在这个长时间运行的过程中始终可以访问我的 DatabaseContext。仅为此方法创建单独的范围?

标签: c#restasp.net-core

解决方案


从 ASP.NET Core 2.1 开始,正确的方法(在 asp.net 中)是扩展BackgroundService(或实现IHostedService)。

传入的请求可以告诉后台服务启动长时间运行的操作并立即返回。您当然需要处理发送重复请求或在现有请求完成之前发送新请求的情况。

文档页面有一个示例,其中BackgroundService读取队列的命令并一次处理一个。

即使 REST 请求已经结束,如何确保在这个长时间运行的过程中始终可以访问我的 DatabaseContext。仅为此方法创建单独的范围?

是的,创建一个单独的范围。

我现在向您提出的问题是,我们是否以错误的方式解决这个问题?我想在 asp.net 控制器中启动这些长时间运行的进程是不好的做法。

我们过去做过类似的事情。只要容错(特别是 wrt 应用程序重新启动)和幂等性内置到长时间运行操作的逻辑中,您就可以开始了。


推荐阅读