Timer应用之Interval优化
Posted 即使如此
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Timer应用之Interval优化相关的知识,希望对你有一定的参考价值。
开发中, 有时有这种场景,使用 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("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 = (ExecTimer.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 + "个变化点是否都发生变化!"); } } }
测试Demo: https://files.cnblogs.com/files/lztkdr/IntervalMgrDemo.zip
以上是关于Timer应用之Interval优化的主要内容,如果未能解决你的问题,请参考以下文章
为啥我要使用 RxJS 的 interval() 或 timer() 轮询而不是 window.setInterval()?