標籤:value event 事件 use images 回呼函數 利用 key extern
項目裡面用到的這些看起來名字高大上的定時器測試下來也是非常不準。看了源碼發現也是用System.Timers.Timer或者用的是Thread休眠的方式來實現的。100毫秒就不準了。直到一番搜尋,發現利用多媒體定時器winmm.dll的MillisecondTimer是可用的。原文來自部落格(dehai)Timer計時不準確的問題及解決方案”。代碼如下:
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; //***************************************************** 屬 性 ******************************************************************* /// <summary> /// /// </summary> 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); } //***************************************************** 方 法 ******************************************************************* /// <summary> /// /// </summary> public void Start() { if (!isRunning) { timerID = timeSetEvent(this.interval, this.resolution, this.timerCallback, 0, 1); // 間隔性地運行 if (timerID == 0) { throw new Exception("無法啟動計時器"); } isRunning = true; } } /// <summary> /// /// </summary> public void Stop() { if (isRunning) { timeKillEvent(this.timerID); isRunning = false; } } /// <summary> /// 實現IDisposable介面 /// </summary> public void Dispose() { timeKillEvent(this.timerID); GC.SuppressFinalize(this); Disposed?.Invoke(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); private void TimerEventCallback(int id, int msg, int user, int param1, int param2) { Tick?.Invoke(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; } }}
測試代碼
class Program { static Dictionary<string, int> dtList = new Dictionary<string, int>(); static void Main(string[] args) { //var timer = new DoubleThreadTimer(100, 100); //timer.OnRunningCallback += Timer1_Tick; //timer.Start(); var timer1 = new MillisecondTimer(); timer1.Interval = 2; timer1.Tick += Timer1_Tick; timer1.Start(); Console.ReadLine(); } private static void Timer1_Tick(object sender, EventArgs e) { var dt = DateTime.Now; string dtStr = dt.ToString("yyyyMMdd HHmmss"); if (dtList.ContainsKey(dtStr)) { dtList[dtStr]++; if (dtList[dtStr] % 500 == 0) { Console.WriteLine(dtStr + "--->" + dtList[dtStr]); dtList.Remove(dtStr); } } else { if (dtList.Count > 1) { foreach (var item in dtList) { Console.WriteLine(item.Key + "--->" + item.Value); } dtList.Clear(); } dtList.Add(dtStr, 1); } } }
測試結論: 時間間隔設定為5毫秒,表現很穩定。2毫秒有時准。可靠性比.net的timer准好多倍啊
Windows高速定時器,多媒體定時器winmm.dll庫的使用