我应该如何在ASP.NET 4中执行长时间运行的任务?
我正在使用.NET 4构build一个网站。有许多从2003年开始使用的MSDN文章,关于使用线程对象和2007年,使用.NET 2中的asynchronous页面 ,但这是非常陈旧的。 我知道.NET 4给我们带来了Task类 , 有些人对此有些模糊警告 。
所以我问你,在ASP.NET 4的IIS下运行后台/asynchronous工作大约在2011年的“首选”方法是什么? 关于直接使用线程/任务有什么警告? Async = true仍然stream行吗?
编辑:好的,好的,从答案很清楚的意见是,如果可以,我应该提供服务。 但是在webapp中做这件事情的好处是很重要的,特别是更容易的部署/重新部署。 假设这个过程是安全的,那么,如果我在IIS里面做,那么最好的办法是什么?
优先避免在这样的环境中执行长时间的任务。
通过互操作性将长时间运行的任务委托给稳定的系统服务,从而使Web应用程序响应并且只需要直接用户请求。
Web应用程序从未(也不是)被认为是可靠的系统 – 任何曾经使用过浏览器的人都会遇到(至less)超时, 这样的不便(对于双方来说)并不局限于这种情况。 当然,任何系统都可能会崩溃,但围绕这样一个事件的环境应该是完全例外的。
Windows服务被devise为长时间运行,如果出现问题,您通常比您的个人服务更担心。
最好避免,但是如果你不得不考虑Hanselman关于如何在ASP.NET中运行后台任务的想法。
其中,为了方便快捷,我build议你特别注意 4.5.2中添加的QueueBackgroundWorkItem 。
从个人经验来看,任务不会削减它。 QueueBackgroundWorkItem好多了。
您可以使用有限的线程编号(例如,只有2)创build一个像http://www.dotnetperls.com/threadpool这样的静态ThreadPool。; 然后在其中排队任务,但是不build议这么做,因为Web服务器不适合这样的任务
我的首选方法与罗伯特·哈维(Robert Harvey)在答案中提出的方法相同。
您仍然可以使用任务并行库 ,但在IIS之外的一个单独的进程中旋转任务(原因是IIS具有有限数量的工作线程分发,并施加其他限制,可能导致长时间运行的任务不可预知)。
这是对“一天一次”的描述。
如果你真的想避免创build一个服务,你可以用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每天不止一次是重要的,你可以在里面创build一个syncronized的代码块(带有一个lock
语句)并且移动里面的lastInvokeDay
检查。
这回答了你的问题了吗?