zoukankan      html  css  js  c++  java
  • 自己开发能在asp.net项目正常使用的定时器WebTimer,让定时器听话起来

    简述:

    iis是一个很不错的服务器,有很多很好用的特性来支持网站运行,但有时候这些特性却会影响到我们开发者的一些操作。比如我们需要定时运行做一些操作,但由于iis的利用应用程序池来管理这种方式会让网站所在的进程在空闲(一段时间没人访问)时注销该线程,所以定时器是无法正常运行的。但利用asp.net的Cache机制是可以巧妙的实现能正常使用的定时器的。

    运行效果:

    请打开该链接

    该网站定时每一个小时给该网页添加一条记录,而且估计我这个站点几百年都不会有一个人来访问一次的,大部分时间都是处于空闲状态的。

    怎么使用:

    网站添加WebTimerLib类库的引用

    在合适的位置编写以下一行代码

     WebTimerLib.WebTimer timer = new WebTimerLib.WebTimer(new System.Threading.TimerCallback(TimeCallback), null, TimeSpan.FromSeconds(2), TimeSpan.FromHours(1));

     或者以下一行代码,推荐这行

    WebTimerLib.WebTimer timer = new WebTimerLib.WebTimer(new System.Threading.TimerCallback(TimeCallback), null, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(60), "20130728");

    这行代码表示2秒后没一个小时运行一次TimeCallback这个方法

    具体每个参数会在源码里有注释

    源码:

    源码是在.net 3.5的环境下开发的,估计.net2.0也是可以编译通过的。

    类库下载地址

    WebTimer类的代码: 

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Text;
      4 using System.Threading;
      5 using System.Web.Caching;
      6 using System.Web;
      7 
      8 namespace WebTimerLib
      9 {
     10     /// <summary>
     11     /// 可以正常在web使用的定时器
     12     /// </summary>
     13     public class WebTimer : IDisposable
     14     {
     15         /// <summary>
     16         /// 初始化 Timer 类的新实例,使用 TimeSpan 值来度量时间间隔。
     17         /// </summary>
     18         /// <param name="callback">一个 TimerCallback 委托,表示要执行的方法。 </param>
     19         /// <param name="state">一个包含回调方法要使用的信息的对象,或者为 空引用(在 Visual Basic 中为 Nothing)。 </param>
     20         /// <param name="dueTime">TimeSpan,表示在 callback 参数调用它的方法之前延迟的时间量。指定 -1 毫秒以防止启动计时器。指定零 (0) 以立即启动计时器。 </param>
     21         /// <param name="period">在调用 callback 所引用的方法之间的时间间隔。指定 -1 毫秒可以禁用定期终止。 </param>
     22         /// <param name="timerID">定时器标识符,不能重复</param>
     23         /// <remarks>
     24         /// 如果 dueTime 为零 (0),则立即调用 callback。如果 dueTime 是 -1 毫秒,则不会调用 callback;计时器将被禁用,但通过调用 Change 方法可以重新启用计时器。
     25         /// 如果 period 为零 (0) 或 -1 毫秒,而且 dueTime 为正,则只会调用一次 callback;计时器的定期行为将被禁用,但通过使用 Change 方法可以重新启用该行为。
     26         /// 为 callback 指定的方法应是可重入的,这是因为 ThreadPool 线程会调用该方法。该方法在以下两种情况下可以同时在两个线程池线程中执行:一是计时器间隔小于执行该方法所需的时间;二是所有线程池线程都在使用,并且多次对该方法进行排队。
     27         /// </remarks>
     28         public WebTimer(TimerCallback callback, Object state, TimeSpan dueTime, TimeSpan period, string timerID)
     29         {
     30             _callback = callback;
     31             _state = state;
     32             _dueTime = dueTime;
     33             _period = period;
     34             _cacheID = timerID;
     35             Run(dueTime);
     36         }
     37 
     38         /// <summary>
     39         /// 初始化 Timer 类的新实例,使用 TimeSpan 值来度量时间间隔, 建议使用WebTimer(TimerCallback callback, Object state, TimeSpan dueTime, TimeSpan period, string timerID),避免造成更改定时器操作的时候,旧操作仍旧在运行
     40         /// </summary>
     41         /// <param name="callback">一个 TimerCallback 委托,表示要执行的方法。 </param>
     42         /// <param name="state">一个包含回调方法要使用的信息的对象,或者为 空引用(在 Visual Basic 中为 Nothing)。 </param>
     43         /// <param name="dueTime">TimeSpan,表示在 callback 参数调用它的方法之前延迟的时间量。指定 -1 毫秒以防止启动计时器。指定零 (0) 以立即启动计时器。 </param>
     44         /// <param name="period">在调用 callback 所引用的方法之间的时间间隔。指定 -1 毫秒可以禁用定期终止。 </param>
     45         /// <param name="timerID">定时器标识符,重复的话会取消之前的任务</param>
     46         /// <remarks>
     47         /// 如果 dueTime 为零 (0),则立即调用 callback。如果 dueTime 是 -1 毫秒,则不会调用 callback;计时器将被禁用,但通过调用 Change 方法可以重新启用计时器。
     48         /// 如果 period 为零 (0) 或 -1 毫秒,而且 dueTime 为正,则只会调用一次 callback;计时器的定期行为将被禁用,但通过使用 Change 方法可以重新启用该行为。
     49         /// 为 callback 指定的方法应是可重入的,这是因为 ThreadPool 线程会调用该方法。该方法在以下两种情况下可以同时在两个线程池线程中执行:一是计时器间隔小于执行该方法所需的时间;二是所有线程池线程都在使用,并且多次对该方法进行排队。
     50         /// </remarks>
     51         public WebTimer(TimerCallback callback, Object state, TimeSpan dueTime, TimeSpan period)
     52         {
     53             _callback = callback;
     54             _state = state;
     55             _dueTime = dueTime;
     56             _period = period;
     57             Run(dueTime);
     58         }
     59 
     60         private TimerCallback _callback;
     61         private object _state;
     62         private TimeSpan _dueTime;
     63         private TimeSpan _period;
     64         private bool _isDisposing = false;
     65         private DateTime _NewDoCallbackTime;
     66 
     67         protected void Run(TimeSpan dueTime)
     68         {
     69             _NewDoCallbackTime = DateTime.Now.Add(dueTime);
     70             HttpRuntime.Cache.Insert(CacheID, this, null, _NewDoCallbackTime, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, new CacheItemRemovedCallback(CacheItemRemovedCallback));
     71 
     72         }
     73 
     74         private void CacheItemRemovedCallback(String key, Object value, CacheItemRemovedReason reason)
     75         {
     76             WebTimer timer = (WebTimer)value;
     77             if (timer._isDisposing)
     78                 return;
     79             if (reason == CacheItemRemovedReason.Expired)
     80             {
     81                 if (timer._period < TimeSpan.FromSeconds(0))
     82                     _isDisposing = true;
     83                 timer._callback(_state);
     84                 timer.Run(timer._period);
     85             }
     86             else
     87             {
     88                 timer.Run(_NewDoCallbackTime - DateTime.Now);
     89             }
     90         }
     91 
     92         /// <summary>
     93         /// 更改计时器的启动时间和方法调用之间的时间间隔,使用 TimeSpan 值度量时间间隔。 
     94         /// </summary>
     95         /// <param name="dueTime">一个 TimeSpan,表示在调用构造 Timer 时指定的回调方法之前的延迟时间量。指定负 -1 毫秒以防止计时器重新启动。指定零 (0) 以立即重新启动计时器。</param>
     96         /// <param name="period">在构造 Timer 时指定的回调方法调用之间的时间间隔。指定 -1 毫秒可以禁用定期终止。 </param>
     97         /// <returns></returns>
     98         public bool Change(TimeSpan dueTime, TimeSpan period)
     99         {
    100             this._dueTime = dueTime;
    101             this._period = period;
    102             try
    103             {
    104                 HttpRuntime.Cache.Remove(CacheID);
    105                 this.Run(this._dueTime);
    106                 return true;
    107             }
    108             catch (Exception)
    109             {
    110                 return false;
    111             }
    112         }
    113 
    114         private string _cacheID;
    115         protected string CacheID
    116         {
    117             get
    118             {
    119                 if (_cacheID == null) _cacheID = GetHashCode().ToString();
    120                 return _cacheID;
    121             }
    122         }
    123 
    124         #region IDisposable 成员
    125 
    126         public void Dispose()
    127         {
    128             _isDisposing = true;
    129         }
    130 
    131 
    132 
    133         #endregion
    134 
    135     }
    136 }

    补充:

    对于我的书写能力我表示歉意,小时候语文没学好,文笔不好请见谅;能力水平有限,有什么说错的地方请多多指教;

    关于转载,我不喜欢别人转载我的文章,觉得有价值的话就收藏到笔记之类软件,不会给搜索引擎收录的地方,我不太关注我的文章的版权问题,但我实在不喜欢自己在网上搜索资料的时候,搜到满满的一页是自己曾写过的一篇文章,实在恶心到我自己,我就注意到了一个情况,很多转载都不是为了学习的,而是一些公司不知道基于什么想法就转了过去,这样造成了搜索自己想要的资源会越来越难。但我发现如果是搜英文的资料的时候就很少有重复的,o(︶︿︶)o 唉,实在纠结啊!

    补充(2013-7-28 7:08):

    喉咙发炎,所以喝水太多,于是半夜起床,看了下定时器的运行情况,发现了奇怪的情况,如下图

    有问题,怎么能安心入眠呢?于是一个经典的场面出现了,一个酷毙(苦逼)的程序猿在夜深人静的时候努力的敲着代码。

    问题在那里呢?认真看运行结果,是不是发现好像有两个定时器在运行呢?没错,就是有两个定时器在运行了。

    原来是我的运行结果用了Cache来保存,运行的站点是个免费的国外空间,估计我们半夜的时候是人家那里烈阳当头的时候,所以出现了内存紧张,我存着结果的Cache给回收了。Cache给回收之后,下次有人访问的时候就会重新设置一个定时器。

    于是发现了一个题外话,有个哥们在1:51分的时候来关顾过我的网站,哦,这个网站运行环境的时候估计和我们有12个小时的时差。

    问题描述出来了,那接下来就是解决

    小弟不用Cache了,直接存在一个文本文件里。

    于是问题解决了,并且我改了定时器的运行周期,半小时一次,然后我们继续等待测试结果吧。

    最后,我对代码做了点修改,修改的范围在53到58行之间,之前有使用的孩纸,就重新复制粘贴下吧,没有的话就不用管这句话了

    更新说明(2013-07-28 9:33)

    重载一个构造函数

    WebTimer(TimerCallback callback, Object state, TimeSpan dueTime, TimeSpan period, string timerID)

  • 相关阅读:
    敏捷开发读后感
    软工第一次作业总结报告
    个人项目作业week5——敏捷开发方法读后感
    结对项目——电梯调度
    个人项目作业
    个人阅读作业3
    个人阅读作业2
    软件工程基础作业-个人项目代码复审
    电梯调度项目总结
    《移山之道》读后感
  • 原文地址:https://www.cnblogs.com/sheepswallow/p/3219612.html
Copyright © 2011-2022 走看看