【转】用ASP.NET模拟Windows Service来实现定时提醒之类的功能
Windows的计划任务大家应该都熟悉,但是怎样在Web上实现类似的功能呢?调用Windows Service不太现实,因为很多时候我们不能去设置服务器自身的环境。
那么我们来考虑如何在Web这种无状态的环境下模拟同样的功能呢?首先我们需要一个回发的事件,这样才能触发我们所要的效果。那么这里有几种方案可以选择:
1、一个页面被请求的时候
2、应用程序的开始和结束
3、一个Session的开始、结束或超时
4、缓存过期
前3种基本不可用,具体原因就不多解释了(b/s的应该都明白),所以只能用第四种。其实主要原理是利用Cache类中的方法
public void Insert ( System.String key , System.Object value ,
System.Web.Caching.CacheDependency dependencies ,
System.DateTime absoluteExpiration ,
System.TimeSpan slidingExpiration ,
System.Web.Caching.CacheItemPriority priority ,
System.Web.Caching.CacheItemRemovedCallback onRemoveCallback )
的最后一个参数,他是一个delegate。
下面是具体实现:
首先我们需要在应用程序开始的时候给程序中注入一个模拟的Cache:
private const string DummyCacheItemKey = "GagaGuguGigi";
protected void Application_Start(Object sender, EventArgs e)
{
RegisterCacheEntry();
}
private bool RegisterCacheEntry()
{
if( null != HttpContext.Current.Cache[ DummyCacheItemKey ] ) return false;
HttpContext.Current.Cache.Add( DummyCacheItemKey, "Test", null,
DateTime.MaxValue, TimeSpan.FromMinutes(1),
CacheItemPriority.Normal,
new CacheItemRemovedCallback( CacheItemRemovedCallback ) );
return true;
}
这里需要注意一下,过期时间只能设为2分钟以上。如果你输入的时间小于2分钟,但仍然是以2分钟计算。(可能是.NET自身的问题)
这样会触发CacheItemRemovedCallback事件,CacheItemRemovedCallback事件的原型如下:
public void CacheItemRemovedCallback( string key,
object value, CacheItemRemovedReason reason)
{
}
在这其中我们可以将我们要做的事情的代码添加进去。
------------------------------------ 分割 ------------------------------------
等等,不要以为这样就完了,这只是你第一次触发了这个事件。在这个事件完了之后,Cache已经被认定为过期,因为我们要想办法重新将新的Cache加进去。
我们的办法是模拟一次页面请求,然后在这次请求里将Cache添加进去:
上面的Callback事件中加入
public void CacheItemRemovedCallback( string key,
object value, CacheItemRemovedReason reason)
{
Debug.WriteLine("Cache item callback: " + DateTime.Now.ToString() );
HitPage();
// Do the service works
DoWork();
}
DoWork()表示你所要做的事情。
HitPage我们这样定义:
private const string DummyPageUrl =
http://localhost/Reminder/WebForm1.aspx;
private void HitPage()
{
WebClient client = new WebClient();
client.DownloadData(DummyPageUrl);
}
模拟页面在执行的时候我们通过Application_BeginRequest这个事件将Cache加入进去
protected void Application_BeginRequest(Object sender, EventArgs e)
{
// If the dummy page is hit, then it means we want to add another item
// in cache
if( HttpContext.Current.Request.Url.ToStri