我应该如何在ASP.NET 4中执行长时间运行的任务?

问题描述:

我正在使用.NET 4构建一个网站。有许多MSDN文章约会从2003, about using Thread objects2007, using Asynchronous Pages in .NET 2,但这是非常陈旧。我知道.NET 4给我们带来了Task classsome people vaguely cautioning against its use for this purpose我应该如何在ASP.NET 4中执行长时间运行的任务?

所以我问你,什么是大约2011年的“首选”方法在IIS 4下运行背景/异步工作?关于直接使用线程/任务有哪些警告? Async = true仍然流行吗?

编辑:好的,好的,从答案很明显,意见是我应该提供服务,如果我可以。但是在webapp中做这件事的好处是很重要的,特别是更容易的部署/重新部署。假设这个过程是安全的,那么,如果我在IIS内部完成这个过程,最好的方法是什么?

优先避免在这样的环境中执行长时间的任务。

通过互操作性将长时间运行的任务委托给稳定的系统服务,从而使Web应用程序响应并且只需要直接用户请求。

Web应用程序从未(也不是)被认为是可靠的系统 - 任何曾经使用过浏览器的人都会遇到(至少)超时,可以肯定的是;这样的不便(对于双方来说)并不限于这种情况。当然,任何系统都可能会崩溃,但围绕系统内置的持久性的情况应该完全例外。

Windows服务旨在长时间运行,如果出现问题,您通常比您的个人服务更担心。

+0

在WAWS上,使用Azure WebJobs – RickAndMSFT 2014-01-21 01:26:52

我的首选方法与Robert Harvey在他的回答中提出的方法相同。

您仍然可以使用Task Parallel Library,但在IIS之外的独立进程中启动任务(原因是IIS具有有限数量的工作线程分发并施加其他限制,从而可能导致长时间运行的任务不可预测)。

+0

您是否有这方面的一个快速示例? – Tigran 2013-02-06 09:29:08

您可以创建一个像线程号为http://www.dotnetperls.com/threadpool这样的静态线程池(例如只有2个)。然后将任务排入其中,但极不推荐,因为Web服务器不适合执行此类任务

这是对“每日一次”方案的描述。

如果你真的想避免创建一个服务,你可以用1分钟的间隔启动一个计时器。每个定时器委托被调用时,你就要跑是这样的(伪代码):

lastInvokeDay = LoadLastInvokeDate(); 
If (lastInvokeDay < DateTime.Now.Date && timeOfDayToRun == DateTime.Now.Time) 
{ 
    try 
    { 
    today = DateTime.Now.Date; 
    runMyTask(); 
    } 
    catch.. 
    finally 
    { 
    lastInvokeDay = today; 
    SaveLastInvokeDay(lastInvokeDay); 
    } 
} 

请记住,lastInvokeDay要么在数据库或文件被保留...

现在,如果要启用立即调用任务,则可以根据需要简单地调用runMyTask()。 如果对于保持runMyTask每天不止一次发生重要,可以在其中创建一个同步代码块(使用lock语句),并将lastInvokeDay检查移入其中。

这是回答您的问题吗?

这是最好的避免,但如果你*,请考虑Hanselman的想法How to run Background Tasks in ASP.NET

其中,为了方便快捷,我建议您特别注意4.5.2中增加的QueueBackgroundWorkItem

从个人经验来看,任务不会削减它。 QueueBackgroundWorkItem更好。