原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, , ); // 间隔性地运行 if (this.timerID == )
{
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;
} }
}

C# winform中自定义精确定时器(经测试稳定可靠)的更多相关文章

  1. Winform中自定义xml配置文件后对节点进行读取与写入

    场景 Winform中自定义xml配置文件,并配置获取文件路径: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100522648 ...

  2. Winform中自定义添加ZedGraph右键实现设置所有Y轴刻度的上下限

    场景 Winforn中实现ZedGraph自定义添加右键菜单项(附源码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...

  3. Winform中自定义ZedGraph右键复制成功后的提示

    场景 Winform中实现ZedGraph中曲线右键显示为中文: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100115292 ...

  4. Winform中自定义xml配置文件,并配置获取文件路径

    场景 在Winform程序中,需要将一些配置项存到配置文件中,这时就需要自定义xml的配置文件格式.并在一些工具类中去获取配置文件的路径并加载其内容. 关注公众号霸道的程序猿获取编程相关电子书.教程推 ...

  5. C# winform中自定义用户控件 然后在页面中调用用户控件的事件

    下面是用户控件的代码: using System; using System.Collections.Generic; using System.ComponentModel; using Syste ...

  6. c#(winform)中自定义ListItem类方便ComboBox添加Item项

    1.定义ListItem类 public class ListItem { private string _key = string.Empty; private string _value = st ...

  7. WinForm中自定义搜索框(水印、清空按钮、加载中图标)

    public partial class CustomSearchBar : TextBox { private readonly Label lblwaterText = new Label(); ...

  8. C# Winform中自定义筛选及自带统计行的Datagridview控件

    网上分享有很多种自制DGV控件,都有不小的缺陷. 没办法,按需求自己定制了一个. 一.过滤方面类似于Excel的筛选功能.支持右键菜单筛选,同时也支持在文本框输入文字按焦点列进行筛选: 二.统计行我采 ...

  9. Winform中对自定义xml配置文件进行Xml节点的添加与删除

    场景 Winform中自定义xml配置文件后对节点进行读取与写入: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10053213 ...

随机推荐

  1. 从PRISM开始学WPF(六)MVVM(三)事件聚合器EventAggregator?

    从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WPF(三)Prism-Region? 从PRISM开始学WPF(四)Prism-Module? ...

  2. stringify 字符串转化成json方法

    参照原文:http://www.cnblogs.com/damonlan/ http://www.jb51.net/article/29893.htm stringify的作用主要是序列化对象(转化为 ...

  3. 火车头采集器对接织梦cms图集发布时, 采集网上图片超时的解决方法

    背景介绍: 火车头采集器对接织梦cms图片集发布时, 对于多张(超过30张)大图片时, 经常会出现图集发布超时的情况.  问题分析: 因为php对于资源的处理有默认的超时时间30秒, 而我尝试了好多方 ...

  4. float、absolute、inline-block三者区别

    0.前言 float属性在css2中是一个热门的属性,被广泛应用于布局之中,同时由于不当使用float带来的问题也非常多,本文结合自己对float的理解以及实际项目中碰到float的相关问题,做一个详 ...

  5. 进军ABP第一天:ABP理论知识

    1.2.3 领域层领域层就是业务层,是一个项目的核心,所有业务规则都应该在领域层实现. ( 实体(Entity ) 实体代表业务领域的数据和操作,在实践中,通过用来映射成数据库表. ( 仓储(Repo ...

  6. hadoop2.6.0实践:引入开发依赖的jar包

    hadoop-2.5.0\share\hadoop\common  所有jar,hadoop-2.5.0\share\hadoop\common\lib  所有jar,hadoop-2.5.0\sha ...

  7. GIT入门笔记(14)- 链接到远程仓库

    1.远程仓库地址https://github.com/ 2.注册远程仓库账号 3.生成ssh-key,并配置到github 由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以, ...

  8. 我的jquery validate 笔记

    <!DOCTYPE html><html lang="en">    <head>    <meta charset="UTF- ...

  9. MongoDB GridFS 存储大文件

    我们经常会遇到这样的场景:上传/下载文件. 有两种思路可以解决这个问题: (1)将文件存储在服务器的文件系统中: (2)将文件存储在数据库中. 如果我们选择(2),那么我们可以使用MongoDB Gr ...

  10. ActiveMQ学习系列(一)

    一.JMS规范 JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消 ...