zoukankan      html  css  js  c++  java
  • c# 高精度的timer

    核心代码摘自 http://www.codeproject.com/Articles/98346/Microsecond-and-Millisecond-NET-Timer

    想用c# (winform)做一个毫秒级别的计时器,发现微软自带的Timer控件经度不够。找到了这段代码,大意是用的 类 System.Diagnostics.Stopwatch 做了一个进一步的封装。

    代码和用法例子如下

    using System;
    namespace MicroLibrary
    {
        /// <summary>
        /// MicroStopwatch class
        /// </summary>
        public class MicroStopwatch : System.Diagnostics.Stopwatch
        {
            readonly double _microSecPerTick =
                1000000D / System.Diagnostics.Stopwatch.Frequency;
    
            public MicroStopwatch()
            {
                if (!System.Diagnostics.Stopwatch.IsHighResolution)
                {
                    throw new Exception("On this system the high-resolution " +
                                        "performance counter is not available");
                }
            }
    
            public long ElapsedMicroseconds
            {
                get
                {
                    return (long)(ElapsedTicks * _microSecPerTick);
                }
            }
        }
    
        /// <summary>
        /// MicroTimer class
        /// </summary>
        public class MicroTimer
        {
            public delegate void MicroTimerElapsedEventHandler(
                                 object sender,
                                 MicroTimerEventArgs timerEventArgs);
            public event MicroTimerElapsedEventHandler MicroTimerElapsed;
    
            System.Threading.Thread _threadTimer = null;
            long _ignoreEventIfLateBy = long.MaxValue;
            long _timerIntervalInMicroSec = 0;
            bool _stopTimer = true;
    
            public MicroTimer()
            {
            }
    
            public MicroTimer(long timerIntervalInMicroseconds)
            {
                Interval = timerIntervalInMicroseconds;
            }
    
            public long Interval
            {
                get
                {
                    return System.Threading.Interlocked.Read(
                        ref _timerIntervalInMicroSec);
                }
                set
                {
                    System.Threading.Interlocked.Exchange(
                        ref _timerIntervalInMicroSec, value);
                }
            }
    
            public long IgnoreEventIfLateBy
            {
                get
                {
                    return System.Threading.Interlocked.Read(
                        ref _ignoreEventIfLateBy);
                }
                set
                {
                    System.Threading.Interlocked.Exchange(
                        ref _ignoreEventIfLateBy, value <= 0 ? long.MaxValue : value);
                }
            }
    
            public bool Enabled
            {
                set
                {
                    if (value)
                    {
                        Start();
                    }
                    else
                    {
                        Stop();
                    }
                }
                get
                {
                    return (_threadTimer != null && _threadTimer.IsAlive);
                }
            }
    
            public void Start()
            {
                if (Enabled || Interval <= 0)
                {
                    return;
                }
    
                _stopTimer = false;
    
                System.Threading.ThreadStart threadStart = delegate()
                {
                    NotificationTimer(ref _timerIntervalInMicroSec,
                                      ref _ignoreEventIfLateBy,
                                      ref _stopTimer);
                };
    
                _threadTimer = new System.Threading.Thread(threadStart);
                _threadTimer.Priority = System.Threading.ThreadPriority.Highest;
                _threadTimer.Start();
            }
    
            public void Stop()
            {
                _stopTimer = true;
            }
    
            public void StopAndWait()
            {
                StopAndWait(System.Threading.Timeout.Infinite);
            }
    
            public bool StopAndWait(int timeoutInMilliSec)
            {
                _stopTimer = true;
    
                if (!Enabled || _threadTimer.ManagedThreadId ==
                    System.Threading.Thread.CurrentThread.ManagedThreadId)
                {
                    return true;
                }
    
                return _threadTimer.Join(timeoutInMilliSec);
            }
    
            public void Abort()
            {
                _stopTimer = true;
    
                if (Enabled)
                {
                    _threadTimer.Abort();
                }
            }
    
            void NotificationTimer(ref long timerIntervalInMicroSec,
                                   ref long ignoreEventIfLateBy,
                                   ref bool stopTimer)
            {
                int timerCount = 0;
                long nextNotification = 0;
    
                MicroStopwatch microStopwatch = new MicroStopwatch();
                microStopwatch.Start();
    
                while (!stopTimer)
                {
                    long callbackFunctionExecutionTime =
                        microStopwatch.ElapsedMicroseconds - nextNotification;
    
                    long timerIntervalInMicroSecCurrent =
                        System.Threading.Interlocked.Read(ref timerIntervalInMicroSec);
                    long ignoreEventIfLateByCurrent =
                        System.Threading.Interlocked.Read(ref ignoreEventIfLateBy);
    
                    nextNotification += timerIntervalInMicroSecCurrent;
                    timerCount++;
                    long elapsedMicroseconds = 0;
    
                    while ((elapsedMicroseconds = microStopwatch.ElapsedMicroseconds)
                            < nextNotification)
                    {
                        System.Threading.Thread.SpinWait(10);
                    }
    
                    long timerLateBy = elapsedMicroseconds - nextNotification;
    
                    if (timerLateBy >= ignoreEventIfLateByCurrent)
                    {
                        continue;
                    }
    
                    MicroTimerEventArgs microTimerEventArgs =
                         new MicroTimerEventArgs(timerCount,
                                                 elapsedMicroseconds,
                                                 timerLateBy,
                                                 callbackFunctionExecutionTime);
                    MicroTimerElapsed(this, microTimerEventArgs);
                }
    
                microStopwatch.Stop();
            }
        }
    
        /// <summary>
        /// MicroTimer Event Argument class
        /// </summary>
        public class MicroTimerEventArgs : EventArgs
        {
            // Simple counter, number times timed event (callback function) executed
            public int TimerCount { get; private set; }
    
            // Time when timed event was called since timer started
            public long ElapsedMicroseconds { get; private set; }
    
            // How late the timer was compared to when it should have been called
            public long TimerLateBy { get; private set; }
    
            // Time it took to execute previous call to callback function (OnTimedEvent)
            public long CallbackFunctionExecutionTime { get; private set; }
    
            public MicroTimerEventArgs(int timerCount,
                                       long elapsedMicroseconds,
                                       long timerLateBy,
                                       long callbackFunctionExecutionTime)
            {
                TimerCount = timerCount;
                ElapsedMicroseconds = elapsedMicroseconds;
                TimerLateBy = timerLateBy;
                CallbackFunctionExecutionTime = callbackFunctionExecutionTime;
            }
    
        }
    
    }

    应用Demo

    public partial class Form1 : Form
        {
             MicroLibrary.MicroTimer  microTimer = null;
            public Form1()
            {
                InitializeComponent();
                MicroTimerTest();
            }
            private void MicroTimerTest()
            {
                // Instantiate new MicroTimer and add event handler
                microTimer = new MicroLibrary.MicroTimer();
                microTimer.MicroTimerElapsed += new MicroLibrary.MicroTimer.MicroTimerElapsedEventHandler(OnTimedEvent);
                microTimer.Interval = 1000; // Call micro timer every 1000µs (1ms)
            }
            int i = 0;
            private void OnTimedEvent(object sender,  MicroLibrary.MicroTimerEventArgs timerEventArgs)
            {
      if (this.IsHandleCreated)
                {
    this.BeginInvoke(new MethodInvoker(delegate { this.textBox1.Text = i.ToString(); })); i++;
    } }
    private void btnStart_Click(object sender, EventArgs e) { microTimer.Enabled = true; } private void btnStop_Click(object sender, EventArgs e) {
    microTimer.Abort(); microTimer.Enabled
    = false; } }
  • 相关阅读:
    python爬虫常见面试题(二)
    python爬虫常见面试题(一)
    回首2018,展望2019
    PDF编辑软件PDFGuru
    打字机NoisyTyper
    文本标注系统
    logstash配置
    服务器上安装python3
    scrapy自调度方案
    前端项目配置nginx配置
  • 原文地址:https://www.cnblogs.com/chengjunwei/p/3643261.html
Copyright © 2011-2022 走看看