2013-04-07 59 views
14

每天一次,我希望我的ASP.NET MVC4网站可能在多台服务器上运行,以便将报告通过电子邮件发送给我。这似乎是一件很常见的事情,但我想要一个很好的方法来做到这一点很困难。如何在ASP.NET MVC网站上执行定期工作?

尝试在服务器上运行计时器来完成这项工作有几个原因是有问题的。如果我有多台服务器,那么我会让计时器在所有服务器上运行(以防服务器故障);我需要在它们之间进行协调,这会变得复杂。此外,试图通过实体框架从后台线程访问数据库增加了复杂性,我必须采用锁定策略来序列化周期性后台线程和“前台”控制器线程之间的DbContext对象的构建/处置。

另一种选择是在服务器上运行一个计时器,但让计时器线程执行一个GET操作,生成一个生成并通过电子邮件发送报告的魔法页面。这解决了DbContext问题,因为数据库访问发生在正常的Controller操作中,并与所有其他Controller访问数据库进行序列化。但是我仍然遇到可能运行多个计时器的问题,所以我需要在Controller动作中使用一些智能来忽略多余的报告请求。

有什么建议吗?这种事情通常如何完成?

+3

快速的答案是,你不应该从网站做到这一点。最简单的解决方案是创建一个可执行文件来为您完成工作并使用任务计划程序进行安排。这取决于您的复杂程度和需求水平,有很多变化,但是从最简单的时间表开始。不要通过网站做到这一点。工作错误的工具。 – Khepri 2013-04-07 06:23:52

回答

13

您不应该从您的web应用程序执行此任务,因为Phil Haack在his blog post中很好地解释了它。

这种事情通常是怎么做的?

您可以从Windows服务甚至计划使用Windows计划程序定期运行的控制台应用程序执行此任务。

+2

如果您在服务器上没有设置计划任务的权限,则可以使用IPPatrol等第三方服务来定期向您的网站发送HTTP请求。 – Dai 2013-04-07 09:00:23

3

正确的解决方案是创建一个独立于您的网站运行的后台服务。但是,如果这不是一个选项,那么您可以使用缓存,如Jeff Atwood在Easy Background Tasks in ASP.NET中所述。

+1

我会注意到'System.Web.Caching.Cache'在内部使用'System.Timers.Timer'实例,所以你可以直接使用它。 – Dai 2013-04-07 09:02:40

+0

完全不推荐的方法。这仍然在Web应用程序中运行,可随时由IIS回收,以消除您可能启动的所有后台任务。实现这一目标的唯一可靠方法是在进程外执行这些任务。 – 2013-04-07 09:12:48

1

有几个选项:

  • 如果您在Azure上托管的网站,看看这是最近发布的预览(http://azure.microsoft.com/en-us/documentation/articles/web-sites-create-web-jobs/
  • WebJobs如果你不想提取出来的痛您的网站之外的电子邮件逻辑,通过url(使用处理程序,mvc操作等)公开该功能,然后运行按计划访问该URL的Windows计划任务。
  • 编写一个简单的控制台应用程序,通过Windows计划任务类似地执行。
  • 或者编写一个简单的Windows服务,它在内部循环并检查时间和到达时间,点击该URL,运行该exe文件,或者使用它自己的代码向您发送电子邮件。