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 + "个变化点是否都发生变化!");
                }
            }
        }
View Code

 

     测试Demo: https://files.cnblogs.com/files/lztkdr/IntervalMgrDemo.zip

                                    

 

              

以上是关于Timer应用之Interval优化的主要内容,如果未能解决你的问题,请参考以下文章

delphi timer用法

VB定时器控件Interval属性设置为0是啥意思

RxJava 创建操作符 timer与interval

为啥我要使用 RxJS 的 interval() 或 timer() 轮询而不是 window.setInterval()?

VB定时器控件Interval属性设置为0是啥意思?

应用层timer_libc