1. 程式人生 > >Timer應用之Interval優化

Timer應用之Interval優化

efi 沒變化 http bool 定義 tps 一點 zip closed

    開發中, 有時有這種場景,使用 Timer 的 Timer_Elapsed 間隔 執行(如:從數據庫)獲取數據 與 現有 應用服務器中的 靜態變量數據(起到緩存的目的)做 對比 ,若有改變,則 更新當前 靜態變量的數據,從而使 數據不再是過期數據,可以繼續被使用的目的。

一般來說,直接使用 Timer 的 Timer_Elapsed 也可以,就是 為了 數據比對,達到效果和目的就行。

     不過在使用過程中,發現自己定義 的靜態變量數據,一般很少情況下,才發生變化, 而 Timer_Elapsed 又總是 固定的時間 Interval 去執行,這樣多少有些浪費資源。

    為了減少 Timer_Elapsed

的執行,就需要 控制 間隔Interval,就此我寫了一個類控制 Interval 的類。

    原理: 將 Timer_Elapsed 中的 “是否變化” 記錄下來,然後 積累多次(集合存儲)的變化後,對其 取 LastCount 個 是否變化, 如果 取出來的 都是 沒有變化,則 Interval 累加 1秒,然後 再提升 LastCount 的個數,以便下次 取更多 是否變化

來確定 是否可以 再次 Interval 累加 1秒。一直持續,當然得控制 Interval 的最大值 ,防止過大失去 更新到最新數據 的作用。還要提供一個 特殊情況,需要 重置 ,重新開始 收集 是否變化

進行計算 的功能。

    效果:技術分享

    代碼如下:

技術分享
 /// <summary>
        /// 管理 Timer 的 Interval
        /// 
        /// 在 Timer 的 Timer_Elapsed 事件中 InsertChangePoint(通過邏輯 得出 這一點的數據是否有變化),將 這一點變化記錄下來,
        /// 
        /// 積累多次 數據變化點,來進行判斷 該變 Timer 的 Interval,從而達到 減少 Timer_Elapsed 執行次數的目的,優化Timer 的作用。
        
/// /// </summary> public class IntervalMgr { public Timer ExecTimer { get;private set; } /// <summary> /// Timer默認間隔 單位(毫秒) /// </summary> public double DefInterval { get; private set; } /// <summary> /// 記錄變化點的容器 /// </summary> public List<bool> LstChangePoint { get; private set; } /// <summary> /// 每次遞增的斷定個數 /// </summary> public int IncLastCount { get; private set; } /// <summary> /// 初始斷定個數 /// </summary> private int LastCount = 0; /// <summary> /// 最大執行間隔 單位(毫秒) /// </summary> public double MaxInterval { get; private set; } /// <param name="execTimer">間隔執行的Timer</param> /// <param name="defInterval">execTimer的默認間隔事件 單位(毫秒)</param> /// <param name="incLastCount">遞增數</param> /// <param name="maxInterval">最大執行間隔 單位(毫秒)</param> public IntervalMgr(Timer execTimer, double defInterval,int incLastCount,double maxInterval = (1000 * 60 * 60)) { this.ExecTimer = execTimer; this.DefInterval = defInterval; this.LastCount = incLastCount; this.IncLastCount = incLastCount; this.MaxInterval = maxInterval; this.LstChangePoint = new List<bool>(); } /// <summary> /// 在 Timer_Elapsed 事件 調用 InsertChangePoint /// </summary> /// <param name="isChange">(檢測數據)是否發生變化</param> public void InsertChangePoint(bool isChange) { LstChangePoint.Add(isChange); //Console.WriteLine("---------------------------------------------"); //Console.WriteLine("LastCount:"+ LastCount + "\r\nLstChangePoint.Count:" + LstChangePoint.Count + "\r\nLstChangePoint:" + string.Join(",", LstChangePoint)); if (CanJudg(LastCount)) { if (JudgIsNotChange(LastCount)) { if ((ExecTimer.Interval + 1000) < MaxInterval)// 小於 最大間隔,則 繼續累加 1 秒 。 { ExecTimer.Interval = (timer.Interval + 1000); LastCount = LastCount + IncLastCount; //下次 要累加 1秒 所需的 檢測變化的個數 } else { ExecTimer.Interval = MaxInterval; //大於 最大間隔,則以 最大間隔 進行執行 LstChangePoint.RemoveRange(0, 1); } } else { //一旦有變化則重置。 ReStart(); } } } /// <summary> /// 特殊情況下,需要執行重置方法 /// </summary> public void ReStart() { LstChangePoint.Clear(); ExecTimer.Interval = DefInterval; LastCount = IncLastCount; } /// <summary> /// 是否可以斷定最後 lastCout 個變化點 /// </summary> /// <param name="lastCout"></param> /// <returns></returns> private bool CanJudg(int lastCout) { if (lastCout <= 0) { return false; } return LstChangePoint.Count >= lastCout; } /// <summary> /// 最後 lastCout 個都沒變化? /// </summary> /// <param name="lastCout"></param> /// <returns></returns> private bool JudgIsNotChange(int lastCout) { if (LstChangePoint.Count >= lastCout) { var lstTake = LstChangePoint.Skip(LstChangePoint.Count - lastCout).Take(lastCout).ToList(); return lstTake.TrueForAll(t => !t);//全部都為false,則就是全部都沒有進行過變化 } else { throw new Exception("積累的變化點還不足以判斷出最後" + lastCout + "個變化點是否都發生變化!"); } } }
View Code

    測試Demo: https://files.cnblogs.com/files/lztkdr/IntervalMgrDemo.zip

Timer應用之Interval優化