A better timer

原文链接:http://www.cnblogs.com/zhy2002/archive/2008/11/16/1334581.html

Windows forms中自带的Timer控件据说精度只有55ms。又有传说在Winnt 4.0以上精度可以达到10ms。

不知道为什么已经没有心情再去考证到底是怎么回事,决定自己写一个:

 

A better timerA better timerCode
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace Model
{
    /// <summary>
    /// 实际上这是一个Timer,此Timer通过另外一个线程实现,定期向主线程投递消息
    /// </summary>
    public class GameLoop
    {
        private readonly int _threadSleep;
        private readonly int _notifierInterval;
        private readonly ILoopProcessor _processor;
        private Thread _timerThread;
        private long _frameCount;
        private Stopwatch _totalWatch = new Stopwatch();

        public GameLoop(AvailableRefreshRates desiredRefreshRate, ILoopProcessor processor)
        {
            _processor = processor;

            if (desiredRefreshRate == AvailableRefreshRates.FPSIs40)
            {
                _threadSleep = 10;  //这个数据是实验得来的在性能和精度上比较平衡的数据
                _notifierInterval = 20; //实际上肯定不会正好是这个数,而是偏大
            }
            else if (desiredRefreshRate == AvailableRefreshRates.FPSIs90)
            {
                _threadSleep = 10;
                _notifierInterval = 10;
            }
            else
            {
                throw new NotSupportedException();
            }
        }

        public void Start()
        {
            _timerThread = new Thread(new ThreadStart(this.Loop));
            _timerThread.IsBackground = true;
            _timerThread.Priority = ThreadPriority.BelowNormal;
            _timerThread.Start();
        }

        public void Loop()
        {
            try
            {
                _totalWatch.Start();
                Stopwatch watch = new System.Diagnostics.Stopwatch();
                double msElapsed = 0;
                watch.Start();
                while (true)
                {
                    System.Threading.Thread.Sleep(_threadSleep);
                    watch.Stop();
                    msElapsed = watch.Elapsed.TotalMilliseconds;
                    if (msElapsed > _notifierInterval)
                    {
                        watch.Reset();
                        watch.Start();
                        _frameCount++;
                        _totalWatch.Stop();
                        double totalElapsed = _totalWatch.Elapsed.TotalMilliseconds;
                        _totalWatch.Start();
                        bool quit = _processor.Process(msElapsed / 1000, _frameCount / (totalElapsed / 1000));

                        if (quit)
                        {
                            watch.Stop();
                            break;
                        }
                    }
                    else
                    {
                        watch.Start();
                    }
                }
            }
            catch (Exception ex)
            {

            }
        }

        public enum AvailableRefreshRates
        {
            FPSIs40, FPSIs90
        }
    }

    public interface ILoopProcessor
    {
        bool Process(double secondsElapsed, double rate);
    }
}

效果:

 

 

A better timer

可以看到刷新率可以达到90桢每秒。

不过我遇到了一个很奇怪的问题,关于Thread.Sleep。当指定的间隔小于10000tick的时候,cpu占用就接近100%,但是只要达到了10000tick,cpu占用立刻就变成0%。不知道是为什么。可能是因为当小于10000tick的时候是用自旋锁实现,大于等于10000tick的时候是用另外的方式实现的。

另外一个十分棘手的问题是屏幕闪烁。在Form上指定的ControlStyle后,仍然有一定的闪烁,难道GDI+的性能就这么成问题?

 

完整的代码:/Files/zhy2002/GDIPlusMovable.rar

转载于:https://www.cnblogs.com/zhy2002/archive/2008/11/16/1334581.html

上一篇:Flutter http 优雅的处理@RquestParam参数


下一篇:HDU 1856 More is better