在.net中执行长时间运行任务的方法
本文关键字:运行 任务 方法 长时间 执行长 net 执行 | 更新日期: 2023-09-27 17:54:10
我正在开发一个相当大的网站,其中包括客户群和计费计划。每月的账单应该自动发生(但是,根据业务规则,员工应该手动单击按钮以启动每个月的流程),并且客户数量在3000 - 5000之间。在每张发票上,价格线都应该基于相当多的参数,甚至是来自web服务的外部数据来计算。
以上肯定是一个(非常)长时间运行的任务,因为应用程序是ASP。. NET MVC网站在IIS上运行,我不希望进程在IIS上运行在它自己的线程中。我担心的是,如果IIS/web服务器发生任何事情,计费计算过程也会停止,这将是至关重要的,至少可以说。
因此,我正在寻找替代方案,并阅读了关于为这样的任务创建Windows服务的内容。是这条路吗?或者是否有其他更"现代"的方式来运行长流程?该过程必须能够从ASP启动。. NET MVC应用。
任何帮助/提示是非常感谢!:-)
几年前我有一个类似的需求。这是用来处理每月会费的。我的做法很简单。首先,在数据库中添加一个表,如下所示:
--------------------------------------
|Monthly Processing Table |
|------------------------------------|
|MonthlyProcessorId int PK |
|ProcessMonth int |
|ProcessYear int |
|HasBeenProcessed bool |
|CanBeProcessed bool |
|ProcessDate DateTime |
|------------------------------------|
当然,您可以添加其他您认为合适的字段。这只是一个示范。
接下来,创建包含按钮的网页,该按钮应该每月按下以开始处理。当按钮被点击时,它应该执行以下逻辑:
- 获取当前月份和年份(
DateTime.Now
) - 在月处理表中查找符合
ProcessMonth
=DateTime.Now.Month
和ProcessYear
=DateTime.Now.Year
的行 - 如果有任何行返回,然后检查行并查看
HasBeenProcessed
是否为true
和ProcessDate
,以查看何时并将此报告给用户并完成。这是一个重要的步骤,因为如果行是返回,HasBeenProcessed
是true
,那么这个月的月费可能已经运行了,您不想向人们收取双倍费用。所以不要跳过这一步,如果HasBeenProcessed
为真,就在这里停止程序执行逻辑! - 如果没有返回行,则创建新行。设置
ProcessMonth
=DateTime.Now.Month
,ProcessYear
=DateTime.Now.Year
。 设置
CanBeProcessed
为true
, HasBeenProcessed
为false
。最后一块拼图是有一个Windows服务,它位于后台,定期从数据库中提取HasBeenProcessed
等于false
和CanBeProcessed
等于true
的所有行。
如果返回任何行,则直接处理,处理后将ProcessDate
设置为DateTime.Now
,将HasBeenProcessed
设置为true
。最后,您的服务将返回定期检查。当我说"定期检查"时,我指的是可能一天一次,甚至可能一周一次,这取决于你的要求。这个服务不应该以任何方式使你的SQL服务器陷入困境。
代替Windows服务,你可以有一个控制台应用程序,计划与Windows调度程序一起运行。不过我更喜欢Windows Service的方式,因为它对我来说"感觉更合适"。
现在,如果你真的想要它,你可以把你的时间表时间和逻辑写在一个接口。这样你就可以重用这个Windows服务。
看起来像是SignalR的一个很好的解决方案:http://www.asp.net/signalr
通常,这是SQL存储过程/代理作业的理想情况,但如果您需要为每个账单调用外部web服务来收集所需的数据,则不是。
只要你有一个账单运行的"头"记录,你就可以很容易地存储你当前在哪个记录上以及运行是否已经完成。无论您是作为windows服务还是作为IIS中的线程运行,都将始终作为一个考虑因素-有人可以在任何时候关闭机器。
SignalR将允许您
- 将运行作为后台任务启动
- 很容易将进度传递回UI
- 允许您从UI停止运行
- 如果用户关闭浏览器,重新连接正在运行的程序
- 监听'completed'事件等
- 允许从多个客户端查看进度
如果它只是一个或两个长时间运行的任务,保持简单,用Windows任务调度程序和c#控制台应用程序来解决这个问题。如果你已经访问了控制台/RDP,那么创建一个计划任务,它将:
-
定期执行,例如每五分钟检查一次是否有工作要做。
-
如果它像运行一个任务一样简单,那么在你的web前端,当用户想要启动你的计费运行时,那么web前端在你的数据库中翻转一个状态标志。
-
计划任务通知您的状态标志已切换到"运行模式"
-
运行计费代码
-
完成后重置"运行模式"
将您的计费运行代码提取出来,以便可以从控制台exe调用。
确保前面提到的计划任务被配置为不启动一个新的实例,如果任务已经在运行(默认值,但在"创建任务"对话框中仔细检查设置选项卡)。
添加一些日志记录,这样你就知道任务已经完成了多少/进度
其他解决方案注意事项:
长时间运行的IIS任务:您的web服务器不是为执行长时间运行的任务而设计的,例如批处理任务,这本质上是您的计费任务。
Windows Services:为什么要重新发明轮子,增加学习编写Windows服务的复杂性