HighAccurateTimer.cs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. using System;
  2. using System.ComponentModel;
  3. using System.Runtime.InteropServices;
  4. using System.Threading;
  5. namespace Masuit.Tools.Systems;
  6. /// <summary>
  7. /// 高精度定时器,1ms精度
  8. /// </summary>
  9. public class HighAccurateTimer : Disposable
  10. {
  11. private readonly long _clockFrequency; // result of QueryPerformanceFrequency()
  12. private bool _running;
  13. private Thread _timerThread;
  14. private int _intervalMs; // interval in mimliseccond;
  15. ///
  16. /// Timer inteval in milisecond
  17. ///
  18. public int Interval
  19. {
  20. get => _intervalMs;
  21. set
  22. {
  23. _intervalMs = value;
  24. _intevalTicks = (long)(value * (double)_clockFrequency / 1000);
  25. }
  26. }
  27. private long _intevalTicks;
  28. [DllImport("Kernel32.dll")]
  29. private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
  30. [DllImport("Kernel32.dll")]
  31. private static extern bool QueryPerformanceFrequency(out long lpFrequency);
  32. public HighAccurateTimer(int interval = 1)
  33. {
  34. if (QueryPerformanceFrequency(out _clockFrequency) == false)
  35. {
  36. // Frequency not supported
  37. throw new Win32Exception("QueryPerformanceFrequency() function is not supported");
  38. }
  39. Interval = interval;
  40. }
  41. public bool GetTick(out long currentTickCount)
  42. {
  43. if (QueryPerformanceCounter(out currentTickCount) == false)
  44. throw new Win32Exception("QueryPerformanceCounter() failed!");
  45. else
  46. return true;
  47. }
  48. public void Start(Action func)
  49. {
  50. _running = true;
  51. _timerThread = new Thread(() =>
  52. {
  53. GetTick(out var currTime);
  54. var nextTriggerTime = currTime + _intevalTicks; // the time when next task will be executed
  55. while (_running)
  56. {
  57. while (currTime < nextTriggerTime)
  58. {
  59. GetTick(out currTime);
  60. } // wailt an interval
  61. nextTriggerTime = currTime + _intevalTicks;
  62. func();
  63. }
  64. })
  65. {
  66. Name = "HighAccuracyTimer",
  67. Priority = ThreadPriority.Highest
  68. };
  69. _timerThread.Start();
  70. }
  71. public void Stop()
  72. {
  73. _running = false;
  74. }
  75. ~HighAccurateTimer()
  76. {
  77. _running = false;
  78. }
  79. /// <summary>
  80. /// 释放
  81. /// </summary>
  82. /// <param name="disposing"></param>
  83. public override void Dispose(bool disposing)
  84. {
  85. Stop();
  86. }
  87. }