C# 利用Kernel32的QueryPerformanceCounter封装的 高精度定时器Timer

在日常的开发过程中,经常 会使用一些定时器做定时循环处理任务;

C# 中的定时器 包括 WinForm 中的System.Windows.Forms.Timer ;System.Timers.Timer ;System.Threading.Timer;

以上方法在实际运行中,在执行一段时间后都会或多或少出现时间精度丢失的情况。

经过测试:System.Windows.Forms.Timer  每各1秒钟要丢失15毫秒左右;

System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed += timer_Elapsed;
timer.Interval = 1000;
timer.AutoReset = true;
timer.Enabled = true;

System.Threading.Timer 每各1秒钟要丢失12~24毫秒左右;

 System.Threading.Timer timer2;
 TimerCallback timerDelegate = new TimerCallback(timer2_Elapsed);
 //创建一个时间间隔为1s的定时器
 timer2 = new System.Threading.Timer(timerDelegate, null, 1000, 1000);

这样子的情况就会导致,原计划每分钟运行60次的,可能运行1分钟后,就会少于60次的情况;

因此在网上找了一个利用系统的Kernel32.dll 的QueryPerformanceCounter提高定时精度的手动封装的计时器;

测试的结果如下,基本保证在毫秒级;

调用方法和System.Windows.Forms.Timer的方法差不多,具体如下:

 // 方法3:启动HighAccurateTimer 定时器
 HighAccurateTimer timer3 = new HighAccurateTimer();
 timer3.Interval = 1000;
 timer3.Elapsed += new HighTimerEventHandler(timer3_Elapsed);
 timer3.Enabled = true;

// 停止定时器
timer3.Enabled = false;
timer3.Destroy();

HighAccurateTimerHelper 封装的代码如下:


using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
 
namespace HighAccurateTimerHelper
{
    /// <summary>
    /// 定时器委托事件的参数
    /// </summary>
    public class TimerEventArgs : EventArgs
    {
        private long clockFrequency;
        public long ClockFrequency
        {
            get { return clockFrequency; }
        }
        private long previousTickCount;
        public long PreviousTickOunt
        {
            get { return previousTickCount; }
        }

        private long currentTickCount;
        public long CurrentTickCount
        {
            get { return currentTickCount; }
        }

        public TimerEventArgs(long clockFreq, long prevTick, long currTick)
        {
            this.clockFrequency = clockFreq;
            this.previousTickCount = prevTick;
            this.currentTickCount = currTick;
        }
    }
    /// <summary>
    /// 高精度定时器事件委托
    /// </summary>
    public delegate void HighTimerEventHandler(object sender, TimerEventArgs e);

    /// <summary>
    ///  高精度定时器,网上找的方法,利用Kernel32的QueryPerformanceCounter提高定时精度
    /// </summary>
    public class HighAccurateTimer
    {
        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);

        [DllImport("Kernel32.dll")]
        private static extern bool QueryPerformanceFrequency(out long lpFrequency);


        public event HighTimerEventHandler Elapsed;

        Thread thread;
        private object threadLock = new object();

        private long clockFrequency = 0;
        private long intevalTicks = 0;
        private long nextTriggerTime = 0;

        private int intervalMs;
        /// <summary>
        /// 定时器间隔
        /// </summary>
        public int Interval
        {
            get
            {
                return intervalMs;
            }
            set
            {
                intervalMs = value;

            }
        }

        private bool enable;
        /// <summary>
        /// 启动定时器标志
        /// </summary>
        public bool Enabled
        {
            get
            {
                return enable;
            }
            set
            {
                enable = value;
                if (value == true)
                {
                    intevalTicks = (long)(((double)intervalMs / (double)1000) * (double)clockFrequency);
                    long currTick = 0;
                    GetTick(out currTick);
                    nextTriggerTime = currTick + intevalTicks;
                }else
                {
                    //Destroy();
                }
            }
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        public HighAccurateTimer()
        {
            if (QueryPerformanceFrequency(out clockFrequency) == false)
            {
                return;
            }
            this.intervalMs = 1000;
            this.enable = false;

            thread = new Thread(new ThreadStart(ThreadProc));
            thread.Name = "HighAccuracyTimer";
            thread.Priority = ThreadPriority.Highest;
            thread.Start();

        }

        /// <summary>
        /// 进程主程序
        /// </summary>
        private void ThreadProc()
        {
            long currTime;
            GetTick(out currTime);
            nextTriggerTime = currTime + intevalTicks;
            while (true)
            {
                while (currTime < nextTriggerTime)
                {
                    GetTick(out currTime); //决定时钟的精度
                }
                nextTriggerTime = currTime + intevalTicks;

                if (Elapsed != null && enable == true)
                {
                    Elapsed(this, new TimerEventArgs(clockFrequency, currTime - intevalTicks, currTime));
                }
            }
        }
        /// <summary>
        /// 获得当前时钟计数
        /// </summary>
        /// <param name="currentTickCount">时钟计数</param>
        /// <returns>获得是否成功</returns>
        public bool GetTick(out long currentTickCount)
        {
            if (QueryPerformanceCounter(out currentTickCount) == false)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        /// <summary>
        /// 注销定时器
        /// </summary>
        public void Destroy()
        {
            enable = false;
            thread.Abort();
        }
    }

}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值