簡述: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)