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

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

 

 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

相关文章:

  • 2021-09-21
  • 2021-12-11
  • 2021-05-27
  • 2022-12-23
  • 2021-11-08
  • 2021-11-10
猜你喜欢
  • 2021-11-19
  • 2021-05-17
  • 2022-12-23
  • 2022-12-23
  • 2022-02-18
  • 2021-08-30
  • 2021-11-01
相关资源
相似解决方案