ASP.NET和计时器

时间:2020-03-06 14:33:45  来源:igfitidea点击:

考虑这段代码...

using System.Threading;
//...
Timer someWork = new Timer(
    delegate(object state) {
        //Do some work here...
    },
    null, 0, 60000);

HttpContext.Current.Application["SomeWorkItem"] = someWork;

这可能很危险吗?在站点运行时在应用程序中缓存计时器以在后台执行一些工作似乎很安全,但是我想知道是否有人对此有所了解。

我敢肯定,编写一个在后台运行的Service肯定会更好,但是有时并不总是这样。这是另一种选择吗?

解决方案

这样做的问题是我们不能保证该过程仍然有效。 IIS基本上会在需要时收回该过程,因此我们冒着无法执行该过程的风险。

如果我们需要完成这项工作,则需要将其编码为Web调用,或者在服务器的后台运行服务。

这将是危险的,因为有时候工作进程会被回收,或者AppDomain崩溃并且工作项被杀死,我们可能希望它恢复正在做的事情,这可能是不可能的。

如果我们可以将工作项放入服务中,则Windows服务可能没问题。如果我们需要一个HttpContext来进行工作,尽管我们可能希望Windows服务调用Web服务来定期进行调用,但这可能并不理想,但是可能会起作用。

这是有道理的,但只是出于娱乐目的,如果在站点关闭的情况下不需要运行该工作怎么办?如果它与Application_Start事件相关联,并且仅在人们浏览网站时才需要运行,那么此时的风险是什么?

好的答案,我只是好奇它在内部如何工作。

我建议我们设置一个计划任务以在网站上运行一个页面。我通常将计划的任务指向带有以下内容的.vbs文件:

On Error Resume Next
Dim objRequest
Dim URL

Set objRequest = CreateObject("Microsoft.XMLHTTP")
URL = "http://www.mywebsite.com/cron/pagetorun.ashx"

objRequest.open "POST", URL , false

objRequest.Send

Set objRequest = Nothing

这通常是一个坏主意,因为System.Threading.Timer使用的是ThreadPool中的线程,与ASP.Net相同。

如果由于某种原因计时器委托被阻止或者停止,则计时器将在超时期限之后简单地开始一个新线程,这将吞噬可用于ASP.net的线程。

如果它们全部开始阻塞,则实际上我们将无法再处理任何Web请求(可能是一件坏事)

Omar Al Zabir在为此目的使用缓存项回调方面有出色的文章。

http://www.codeproject.com/KB/aspnet/ASPNETService.aspx?fid=229682&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=76&select=1334820