本身開發能在asp.net項目正常使用的定時器WebTimer,讓定時器聽話起來

簡述:web

iis是一個很不錯的服務器,有不少很好用的特性來支持網站運行,但有時候這些特性卻會影響到咱們開發者的一些操做。好比咱們須要定時運行作一些操做,但因爲iis的利用應用程序池來管理這種方式會讓網站所在的進程在空閒(一段時間沒人訪問)時註銷該線程,因此定時器是沒法正常運行的。但利用asp.net的Cache機制是能夠巧妙的實現能正常使用的定時器的。服務器

運行效果:asp.net

請打開該連接ide

該網站定時每個小時給該網頁添加一條記錄,並且估計我這個站點幾百年都不會有一我的來訪問一次的,大部分時間都是處於空閒狀態的。函數

怎麼使用:學習

網站添加WebTimerLib類庫的引用測試

在合適的位置編寫如下一行代碼網站

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

 或者如下一行代碼,推薦這行this

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)

相關文章
相關標籤/搜索