如何在WPF中准确使用调度定时器来控制帧速率

本文关键字:定时器 调度 控制 帧速率 控制帧 WPF | 更新日期: 2023-09-27 18:01:05

当我试图使用System.Windows.Threading.DispatcherTimer实例控制WPF中的帧速率时,遇到了一个问题。

为了尝试DispatcherTimer的有效性,我创建了一个简单的WPF演示,其中有一个文本框和一个按钮。单击该按钮时,DispatcherTimer实例开始根据文本框中作为间隔的双数进行计时,StopWatch同时启动,计数器变量在每个DispatcherTimer计时时增加1。当StopWatch.ElaspedMilliSeconds>1000(超过1秒(时,计时器停止计时,秒表也会重置,此时会弹出一个显示计数器值的消息框。

因此,如果我输入33.3(1000/30(,计数器值应该在30左右。但结果是在20左右。我请求帮助是否有人可以帮助检查下面我的源代码中的问题。提前谢谢。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TimerDemo
{
   public partial class MainWindow : Window
   {
      private System.Windows.Threading.DispatcherTimer _timer = new System.Windows.Threading.DispatcherTimer();
      public MainWindow()
      {
         InitializeComponent();
         double ticks = 0L;
         System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
         int frameCount = 0;
         //There is a textbox "txtTicks" which accepts a millisecond value
         //And a button "btn", by clicking the button the dispatchertimer & 
         //stopwatcher are started.
         _timer.Tick += (sender, e) =>
         {
            frameCount++;
            System.Diagnostics.Debug.WriteLine(watch.ElapsedMilliseconds);
            if (watch.ElapsedMilliseconds > 1000)
            {
               _timer.Stop();
               watch.Reset();
               MessageBox.Show(string.Format("Already 1 second! FrameCount: {0}", frameCount));
               frameCount = 0;
            }
         };
         this.btn.Click += (sender, e) =>
         {
            double.TryParse(this.txtTicks.Text, out ticks);
            if (ticks != 0.0)
            {
               _timer.Interval = TimeSpan.FromMilliseconds(ticks);
            }
            _timer.Start();
            watch.Start();
         };
      }
   }
}

运行结果如下(堆栈溢出的新手,还不能上传图像(:

https://i.stack.imgur.com/u6W2s.png

如何在WPF中准确使用调度定时器来控制帧速率

由于WPF(和大多数其他渲染引擎(渲染每一帧所需的时间并不相等,而且不同的计算可能会进一步延迟帧之间的间隔,因此使用CompositionTarget.Rendering来"计时"渲染间隔是正确的,但您仍然可以使用"挂钟"计时器以规则、严格控制的间隔更新游戏。

在优秀的书籍"游戏编程模式"(在线免费提供(中,你可以找到非常有用的游戏循环模式。

在其完整形式中,这是您将放在CompositionTarget.Rendering事件的处理程序中的内容(以伪代码形式(:

双电流=getCurrentTime((;双倍运行时间=当前-以前;previor=当前;lag+=经过;processInput((;而(滞后>=MS_PER_UPDATE({update((;滞后-=MS_PER_UPDATE;}render((;

例如,在C#中,可以通过调用DateTime.Now或使用Stopwatch.Elapsed来实现getCurrentTime()