C\#고정 밀 타이머 만 들 기 예시

10106 단어 c#고밀도타이머
배경
 우 리 는.NET Framework 에 네 가지 자주 사용 하 는 타이머 가 존재 한 다 는 것 을 알 고 있다.그들 은 각각 다음 과 같다.
1 두 개 는 일반적인 다 중 스 레 드 타이머 입 니 다.
  • System.Threading.Timer
  • System.Timers.Timer
  • 2 두 개 는 전용 단일 스 레 드 타이머 입 니 다.
  • System.Windows.Forms.Timer (Windows Forms 의 타이머)
  • System.Windows.Threading.DispatcherTimer (포 토 타임
  • 보통 그들의 정 도 는 10-20ms 사이 만 유지 할 수 있 습 니 다.이것 은 운영 체제 와 관련 이 있 기 때문에 우 리 는 많은 장면 에서 이것 은 우리 의 정밀도 에 이 르 지 못 합 니 다.이런 수 요 를 실현 하려 면 우 리 는 어떻게 해 야 합 니까?물론 여러 가지 방법 도 있 습 니 다.오늘 은 주로 Stopwatch 가 실현 하 는 방식 을 소개 합 니 다.인터넷 상에 서 Win 32 Dll 을 사용 하 는 API 가 많 습 니 다.이것 은 당연히 가능 합 니 다.이 글 의 중점 은 이것 을 토론 하 는 것 이 아니 라 Win 32 API 를 사용 하 는 방식 에 대해 참고 할 수 있 습 니 다.
    이루어지다
    
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
     
    namespace Pangea.Common.Utility
    {
        /// <summary>
        /// .Net Stopwatch              
        /// DeviceTimer    Stopwatch          
        /// </summary>
        public sealed class DeviceTimer
        {
    #if USE_CPU_COUNTING
            //        API,   CPU      
            [DllImport("Kernel32.dll")]
            private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
     
            //    CPU     
            [DllImport("Kernel32.dll")]
            private static extern bool QueryPerformanceFrequency(out long lpFrequency);
    #else
            /// <summary>
            ///   TickCount64  
            /// </summary>
            /// <returns></returns>
            //[DllImport("kernel32.dll")]
            //public static extern long GetTickCount64();
    #endif
            private enum DeviceTimerState
            {
                TM_ST_IDLE = 0,
                TM_ST_BUSY = 1,
                TM_ST_TIMEOUT = 2,
            }
     
            /// <summary>
            /// Stopwatch object
            /// </summary>
            Stopwatch _stopWatch = new Stopwatch();
     
            /// <summary>
            ///        
            /// </summary>
            DeviceTimerState _state;
     
            /// <summary>
            ///                
            /// </summary>
            long _startTime;
     
            /// <summary>
            ///              
            /// </summary>
            long _timeOut;
     
    #if USE_CPU_COUNTING
     
            /// <summary>
            /// CPU       
            /// </summary>
            double _freq;
    #endif
     
            /// <summary>
            ///     (  :ms)
            /// </summary>
            double _duration;
     
            /// <summary>
            /// class constructure
            /// </summary>
            public DeviceTimer()
            {
    #if USE_CPU_COUNTING
                long freq;
                if (QueryPerformanceFrequency(out freq) == false)
                    throw new Exception("             ");
                //   1ms CPU  TickCount  
                _freq = (double)freq / 1000.0;
                QueryPerformanceCounter(out _startTime);
    #else
                _stopWatch.Start();
                _startTime = 0;
    #endif
                SetState(DeviceTimerState.TM_ST_IDLE);
                _timeOut = _startTime;
                _duration = 0;
            }
     
            /// <summary>
            ///     :         
            /// </summary>
            /// <param name="state"></param>
            private void SetState(DeviceTimerState state)
            {
                _state = state;
            }
     
            /// <summary>
            ///     :         
            /// </summary>
            /// <returns></returns>
            private DeviceTimerState GetState()
            {
                return _state;
            }
     
            /// <summary>
            ///                 (  :  )
            /// </summary>
            /// <returns></returns>
            public double GetElapseTime()
            {
                long curCount;
    #if USE_CPU_COUNTING
                QueryPerformanceCounter(out curCount);
                return (double)(curCount - _startTime) / (double)_freq;
    #else
                curCount = _stopWatch.ElapsedMilliseconds;
                return curCount - _startTime;
    #endif
            }
     
            /// <summary>
            ///        
            /// </summary>
            /// <returns></returns>
            public double GetTotalTime()
            {
                return _duration;
            }
     
            /// <summary>
            ///        
            /// </summary>
            public void Stop()
            {
                SetState(DeviceTimerState.TM_ST_IDLE);
    #if USE_CPU_COUNTING
                QueryPerformanceCounter(out _startTime);
    #else
                _startTime = _stopWatch.ElapsedMilliseconds;
    #endif
                _timeOut = _startTime;
                _duration = 0;
            }
     
            /// <summary>
            ///      
            /// </summary>
            /// <param name="delay_ms">    (  :  )</param>
            public void Start(double delay_ms)
            {
    #if USE_CPU_COUNTING
                QueryPerformanceCounter(out _startTime);
                _timeOut = Convert.ToInt64(_startTime + delay_ms * _freq);
    #else
                _startTime = _stopWatch.ElapsedMilliseconds;
                _timeOut = Convert.ToInt64(_startTime + delay_ms);
    #endif
                SetState(DeviceTimerState.TM_ST_BUSY);
                _duration = delay_ms;
            }
     
            /// <summary>
            ///        
            ///            Start     
            /// </summary>
            /// <param name="delay_ms">    (  :  )</param>
            public void Restart(double delay_ms)
            {
    #if USE_CPU_COUNTING
                _timeOut = Convert.ToInt64(_startTime + delay_ms * _freq);
    #else
                _timeOut = Convert.ToInt64(_startTime + delay_ms);
    #endif
                SetState(DeviceTimerState.TM_ST_BUSY);
                _duration = delay_ms;
            }
     
            /// <summary>
            ///          
            /// </summary>
            /// <returns></returns>
            public bool IsTimeout()
            {
                if (_state == DeviceTimerState.TM_ST_IDLE)
                {
                    //System.Diagnostics.Debug.WriteLine("Warning: Misuage of the device timer. You must start it first before you can use it.");
                    //System.Diagnostics.Debug.Assert(false, "Warning: Misuage of the device timer. You must start it first before you can use it.");
                }
                long curCount;
    #if USE_CPU_COUNTING
                QueryPerformanceCounter(out curCount);
    #else
                curCount = _stopWatch.ElapsedMilliseconds;
    #endif
                if (_state == DeviceTimerState.TM_ST_BUSY && (curCount >= _timeOut))
                {
                    SetState(DeviceTimerState.TM_ST_TIMEOUT);
                    return true;
                }
                else if (_state == DeviceTimerState.TM_ST_TIMEOUT)
                {
                    return true;
                }
                return false;
            }
     
            /// <summary>
            ///          
            /// </summary>
            /// <returns></returns>
            public bool IsIdle()
            {
                return (_state == DeviceTimerState.TM_ST_IDLE);
            }
        }
    }
    이 안에서 우 리 는 DeviceTimer 에서 개인 적 인 을 정의 했다.stopWatch 대상 과 구조 함수 에서 이 Stopwatch 를 시 작 했 습 니 다.그래서 우 리 는 사용 할 때 DeveiceTimer 대상 을 만 든 다음 에 내부 의 Start 방법 을 호출 합 니 다.물론 이 방법 을 호출 할 때 우 리 는 정시 시간 을 입력 한 다음 에 IsTimeout 방법 이 정시 시간 에 도 착 했 는 지 계속 검 측 해 야 합 니 다.따라서 정시 시간 과 유사 한 효 과 를 얻 을 수 있 습 니 다.또한 GetElapseTime()방법 은 Start 방법 을 호출 하 는 것 부터 지금까지 의 시간 을 얻 을 수 있 습 니 다.또한 우 리 는 그 중에서 몇 개의 매 거 진 값 을 정의 하여 현재 DeviceTimer 의 상 태 를 표시 하여 일부 상 태 를 검사 하 는 데 사용 할 수 있 습 니 다.구체 적 인 수 치 는 다음 과 같 습 니 다.
    
    private enum DeviceTimerState
    {
        TM_ST_IDLE = 0,
        TM_ST_BUSY = 1,
        TM_ST_TIMEOUT = 2,
    }
    여기 서 마지막 문 제 는 바로 순환 호출 문제 입 니 다.이것 도 아주 간단 합 니 다.While 순환 에서 계속 호출 되 고 있 습 니 다.물론 아래 의 코드 는 우리 가 발휘 할 수 있 는 많은 내용 이 있 습 니 다.이것 은 자신의 수요 에 따라 수정 할 수 있 습 니 다.
    
    using System;
    using System.Threading.Tasks;
     
    namespace DeviceTimerConsoleApp
    {
        class Program
        {
            private static bool flag = true;
            static void Main(string[] args)
            {
                Task.Factory.StartNew(() =>
                {
                    var deviceTimer = new DeviceTimer();
                    deviceTimer.Start(5);
     
                    while (flag)
                    {
                        if (deviceTimer.IsTimeout())
                        {
                            Console.WriteLine($"      ,         :{deviceTimer.GetElapseTime()}ms");
     
                            deviceTimer.Start(5);
                        }
                    }
                });
                Console.ReadKey();
            }
        }
         
    }
    타이머 효과 한번 볼 게 요.

    이상 은 C\#고정 밀 타 이 머 를 만 드 는 예제 의 상세 한 내용 입 니 다.C\#고정 밀 타 이 머 를 만 드 는 데 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!

    좋은 웹페이지 즐겨찾기