原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; } } }