zoukankan      html  css  js  c++  java
  • C# winform中自定义精确定时器(经测试稳定可靠)

     https://github.com/aelassas/Wexflow/wiki

    原C#的定时器时间越长,误差越大。

    在主动请求设备数据的使用,使用C#的几种自带定时器导致每天都会丢失几条数据。

    经测试使用自定义的定时器可完全解决此问题。

    使用方法:

    MillisecondTimer _sysTimer;

    _sysTimer = new MillisecondTimer();
    _sysTimer.Tick += sysTimer_Tick; ;
    _sysTimer.Interval = 1000; //每秒执行
    _sysTimer.Start();

    private void sysTimer_Tick(object sender, EventArgs e)
    {

    //需要定时执行的内容

    }

    自定义类(MillisecondTimer.cs)如下:

    复制代码
    using System;
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    
    namespace TEST
    {
        public sealed class MillisecondTimer : IComponent, IDisposable
        {
    
            private static TimerCaps caps;
            private int interval;
            private bool isRunning;
            private int resolution;
            private TimerCallback timerCallback;
            private int timerID;
    
            public int Interval
            {
                get
                {
                    return this.interval;
                }
                set
                {
                    if ((value < caps.periodMin) || (value > caps.periodMax))
                    {
                        throw new Exception("超出计时范围!");
                    }
                    this.interval = value;
                }
            }
    
            /// <summary>
            /// 
            /// </summary>
            public bool IsRunning
            {
                get
                {
                    return this.isRunning;
                }
            }
    
            /// <summary>
            /// 
            /// </summary>
            public ISite Site
            {
                set;
                get;
            }
    
            public event EventHandler Disposed;  // 这个事件实现了IComponet接口
            public event EventHandler Tick;
    
            static MillisecondTimer()
            {
                timeGetDevCaps(ref caps, Marshal.SizeOf(caps));
            }
    
            public MillisecondTimer()
            {
                this.interval = caps.periodMin;    // 
                this.resolution = caps.periodMin;  //
    
                this.isRunning = false;
                this.timerCallback = new TimerCallback(this.TimerEventCallback);
    
            }
    
            public MillisecondTimer(IContainer container)
                : this()
            {
                container.Add(this);
            }
    
            ~MillisecondTimer()
            {
                timeKillEvent(this.timerID);
            }
    
            public void Start()
            {
                if (!this.isRunning)
                {
                    this.timerID = timeSetEvent(this.interval, this.resolution, this.timerCallback, 0, 1); // 间隔性地运行
    
                    if (this.timerID == 0)
                    {
                        throw new Exception("无法启动计时器");
                    }
                    this.isRunning = true;
                }
            }
    
            public void Stop()
            {
                if (this.isRunning)
                {
                    timeKillEvent(this.timerID);
                    this.isRunning = false;
                }
            }
    
            /// <summary>
            /// 实现IDisposable接口
            /// </summary>
            public void Dispose()
            {
                timeKillEvent(this.timerID);
                GC.SuppressFinalize(this);
                EventHandler disposed = this.Disposed;
                if (disposed != null)
                {
                    disposed(this, EventArgs.Empty);
                }
            }
    
    
            //***************************************************  内部函数  ******************************************************************
            [DllImport("winmm.dll")]
            private static extern int timeSetEvent(int delay, int resolution, TimerCallback callback, int user, int mode);
    
    
            [DllImport("winmm.dll")]
            private static extern int timeKillEvent(int id);
    
    
            [DllImport("winmm.dll")]
            private static extern int timeGetDevCaps(ref TimerCaps caps, int sizeOfTimerCaps);
            //  The timeGetDevCaps function queries the timer device to determine its resolution. 
    
    
    
            private void TimerEventCallback(int id, int msg, int user, int param1, int param2)
            {
                if (this.Tick != null)
                {
                    this.Tick(this, null);  // 引发事件
                }
            }
    
    
            //***************************************************  内部类型  ******************************************************************
    
            private delegate void TimerCallback(int id, int msg, int user, int param1, int param2); // timeSetEvent所对应的回调函数的签名
    
    
            /// <summary>
            /// 定时器的分辨率(resolution)。单位是ms,毫秒
            /// </summary>
            [StructLayout(LayoutKind.Sequential)]
            private struct TimerCaps
            {
                public int periodMin;
                public int periodMax;
            }
    
        }
    }
    复制代码

    https://www.cnblogs.com/bunsen/p/7240511.html

  • 相关阅读:
    解决方案下显示的网站名称被追加编号的问题解决方法
    sql server 2008 报表服务器(sql server 2008 report service)中如何固定行或者列
    如何通过参数来切换图表和数据
    饼图中如何将一定比例的小切片收集在一起
    饼图图例中显示百分比值
    如何根据条件隐藏列
    饼图上如何显示百分比值
    负载均衡
    在UTF8页中接收和使用以GB2312方式进行URL编码的中文数据
    ASP 格式化显示时间为几个月,几天前,几小时前,几分钟前,或几秒前
  • 原文地址:https://www.cnblogs.com/robertyao/p/10315571.html
Copyright © 2011-2022 走看看