在.NET中执行长时间运行任务的方法

时间:2015-06-08 14:24:33

标签: c# asp.net asp.net-mvc iis service

我正在开发一个相当大的网站,其中包括客户群和结算方案。每月结算应该自动进行(但是,由于业务规则,员工应该每月手动点击按钮启动流程),客户数量在3000 - 5000之间。在每张发票上,价格线应该是基于相当多的参数甚至来自Web服务的外部数据计算。

以上肯定是一个(非常)长时间运行的任务,因为应用程序是在IIS上运行的ASP.NET MVC网站,我不希望该进程在其自己的线程中运行IIS。我担心的是,如果IIS /网络服务器发生任何事情,计费计算过程也会停止,这至少可以说是至关重要的。

因此,我正在寻找替代方案并阅读有关为此类任务创建Windows服务的信息。这是要走的路吗?或者还有其他,可能更多"现代"运行长流程的方法?该过程必须能够从ASP.NET MVC应用程序启动。

非常感谢任何帮助/提示! : - )

3 个答案:

答案 0 :(得分:1)

几年前我确实要求做类似的事情。这是为了处理每月会费。我这样做很简单。首先,在您的数据库中,添加一个类似于此的表:

--------------------------------------
|Monthly Processing Table            |
|------------------------------------|
|MonthlyProcessorId       int     PK |
|ProcessMonth             int        |
|ProcessYear              int        |
|HasBeenProcessed         bool       |
|CanBeProcessed           bool       |
|ProcessDate              DateTime   |
|------------------------------------|

当然,您可以根据需要添加其他字段。这仅用于演示。

接下来,创建一个网页,其中包含应按月按下以开始处理的按钮。当按钮被击中时,它应该执行以下逻辑:

  1. 获取当前月份和年份(DateTime.Now
  2. 在每月处理表中搜索匹配ProcessMonth等于DateTime.Now.MonthProcessYear等于DateTime.Now.Year的行。
  3. 如果有任何行返回,请检查该行并查看HasBeenProcessedtrueProcessDate以查看何时向用户报告并完成此操作。这是一个重要的步骤,因为如果行是返回而HasBeenProcessedtrue,那么月费可能已经在本月运行,并且您不希望对人员加倍。因此,如果HasBeenProcessed为真,请不要跳过此步骤并停止程序执行逻辑!
  4. 如果没有返回任何行,则创建一个新行。将ProcessMonth设置为DateTime.Now.Month,将ProcessYear设置为DateTime.Now.Year。将CanBeProcessed设为true,将HasBeenProcessed设为false
  5. 最后一个难题是拥有一个位于后台的Windows服务,并定期从HasBeenProcessed等于falseCanBeProcessed等于true的数据库中提取所有行到ProcessDate

    如果返回任何行,则只需处理它们,然后在处理它们之后,将DateTime.Now设置为HasBeenProcessed并将true设置为erase()。最后,您的服务只是回到定期检查。当我说“定期检查”时,我说的可能是每天一次,甚至每周一次,这取决于你的要求。这项服务不应该以任何方式阻碍你的SQL服务器。

    您可以拥有一个计划与Windows Scheduler一起运行的控制台应用程序,而不是Windows服务。我更喜欢Windows服务方式,因为它对我来说“感觉更合适”。

    现在,如果您想真正了解它,可以在界面中编写计划时间和逻辑。通过这种方式,您可以在未来重复使用此Windows服务。

答案 1 :(得分:0)

看起来是SignalR的一个很好的解决方案:http://www.asp.net/signalr

通常情况下,这将是SQL存储过程/代理作业的理想情况,但如果您需要为每个帐单调用外部Web服务来收集所需数据,则不会这样做。

只要你有一个标题'对于账单运行记录,您可以轻松存储您当前所在的记录以及运行是否已完成。无论您是作为Windows服务还是IIS中的线程运行,始终都是一个考虑因素 - 有人可能随时关闭计算机。

SignalR将允许你

  • 将运行作为后台任务启动
  • 轻松将进度传回UI
  • 允许您停止UI的运行
  • 如果用户关闭浏览器
  • ,则重新连接到正在进行的运行
  • 聆听'已完成'事件等
  • 允许从多个客户端看到进度

答案 2 :(得分:0)

如果它只是一个或两个长时间运行的任务,请保持简单,并使用Windows任务计划程序和C#控制台应用程序解决此问题。如果您有权访问控制台/ RDP,则创建一个计划任务,该任务将:

  1. 定期执行,比如每五分钟检查一次工作。

  2. 如果它只是运行一个任务那么简单,那么在您的Web前端,当用户想要开始计费运行时,Web前端会在您的数据库中翻转状态标志。

  3. 计划任务通知您的状态标志已翻转为“运行模式”

  4. 运行结算代码。

  5. 完成后,重置“运行模式”

  6. 先决条件 -

    1. 将您的结算运行代码计算出来,以便可以从控制台exe调用它。

    2. 确保上述计划任务配置为在任务已经运行时不启动新实例(默认情况下,但请仔细检查“创建任务”对话框中的设置选项卡)。

    3. 添加一些日志记录,以便您知道已完成/进度的任务有多少

    4. 其他解决方案注意事项:

      • 长时间运行IIS任务:您的Web服务器并非设计用于执行长时间运行的任务,例如批处理作业,这实际上就是您的结算任务。

      • Windows服务:为什么重新发明轮子,增加了学习编写Windows服务的复杂性。