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

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

时间: 2024-10-14 05:30:16

Timer应用之Interval优化的相关文章

AngularJS性能优化心得,自己踩过的抗,及一些别人的经验(转哦)

脏数据检查 != 轮询检查更新 谈起angular的脏检查机制(dirty-checking), 常见的误解就是认为: ng是定时轮询去检查model是否变更.其实,ng只有在指定事件触发后,才进入$digest cycle: DOM事件,譬如用户输入文本,点击按钮等.(ng-click) XHR响应事件 ($http) 浏览器Location变更事件 ($location) Timer事件($timeout, $interval) 执行$digest()或$apply() 参考<masteri

angular性能优化心得

脏数据检查 != 轮询检查更新 谈起angular的脏检查机制(dirty-checking), 常见的误解就是认为: ng是定时轮询去检查model是否变更.其实,ng只有在指定事件触发后,才进入$digest cycle: DOM事件,譬如用户输入文本,点击按钮等.(ng-click) XHR响应事件 ($http) 浏览器Location变更事件 ($location) Timer事件($timeout, $interval) 执行$digest()或$apply() 参考<masteri

muduo::TimerId、Timer、TimerQueue分析

Linux时间函数介绍 linux中用以获取当前时间的的函数有 定时函数 timerfd介绍 TimerId介绍 Timer TimerQueue Linux时间函数介绍 linux中用以获取当前时间的的函数有: time(2) / time_t(秒) ftime(3) / struct timeb(毫秒) gettimeofday(2) / struct timeval(微秒) clock_gettime(2) / struct timespec(微秒) 还有gmtime / localtim

System.Windows.Forms.Timer反编译学习

1 using System; 2 using System.ComponentModel; 3 using System.Globalization; 4 using System.Runtime; 5 using System.Runtime.InteropServices; 6 using System.Threading; 7 namespace System.Windows.Forms 8 { 9 [DefaultEvent("Tick"), DefaultProperty(

timer控件的使用

timer控件还是比较简单的 直接在控件中找到timer拖拽到form上,直接双击timer1控件,直接在private void timer1_Tick(object sender, EventArgs e)方法中写入你需要不断执行的代码,时间间隔在timer的属性Interval设置(1000=1s) 例如需要实现扫描二维码实现登陆的功能的话(现有的webserver,可以不停的读取服务器是否获取到数据,有则返回数据) 创建二维码可以外部应用dll文件,调用方法直接生成,这里就不累赘说了 然

System.Windows.Forms.Timer的简单用法

Timer就是用来计时操作,如:你想在多少秒之后执行某个动作 Timer showTextBoxTimer = new Timer(); //新建一个Timer对象 showTextBoxTimer.Interval = 1000;//设定多少秒后行动,单位是毫秒 showTextBoxTimer.Tick += new EventHandler(showTextBoxTimer_Tick);//到时所有执行的动作 showTextBoxTimer.Start();//启动计时

三种timer控件的简单实例

1 1.system.windows.forms 2 3 2.system.threading.timer 4 5 3.system.timers.timer 6 7 8 9 using System; 10 using System.Collections.Generic; 11 using System.ComponentModel; 12 using System.Data; 13 using System.Drawing; 14 using System.Linq; 15 using S

Linux时间子系统(六) POSIX timer

一.前言 在用户空间接口函数文档中,我们描述了和POSIX timer相关的操作,主要包括创建一个timer.设定timer.获取timer的状态.获取timer overrun的信息.删除timer.本文将沿着这些用户空间的接口定义来看看内核态的实现.虽然POSIX timer可以基于各种不同的clock创建,本文主要描述real time clock相关的timer. 本文第二章描述了POSIX timer的基本原理,第三章描述系统调用的具体实现,第四章主要讲real time clock的

使用Timer组件制作计时器

实现效果: 知识运用: Timer组件的interval属性 //获取或设置Timer组件Tick事件发生的时间间隔 public int Interval {get;set} NumericUpDown控件的Value属性 //获取或设置数字显示框的值 public decimal Value {get;set;} 实现代码: private void button1_Click(object sender, EventArgs e) { DateTime get_time1 = DateTi