在OnPaint中Winforms Frameratelock?

zok*_*r13 1 c# onpaint winforms

我正在尝试改进我的应用程序并提高它的性能.基本上,它是一个高级的Graph-class.它绘制了几行并刷新它们.

在确定了几个慢点之后,我想对我的结果进行基准测试.我的绘图卡在~65 FPS(这是完美的,但我是基准测试).我在一个计时器(设置为1毫秒)中使我的对象无效,并使用受保护的覆盖void OnPaint - "way"重绘我的东西.

之后,我将Invalidate()放入受保护的覆盖void OnPaint中.事后FPS设定为几千.但使用该方法将导致空屏幕.

我的问题是:这个问题是故意的吗?这是有道理的,因为高于屏幕刷新率的任何东西都是浪费的力量.但我想为我的基准测试禁用"锁定".

示例代码:

//Timer to refresh
private void timer1_Tick(object sender, EventArgs e)
    {
        Invalidate();
    }

private DateTime date = DateTime.UtcNow;
    private long times = 0;
    protected override void OnPaint(PaintEventArgs e)
    {

        base.OnPaint(e);

        //Drawing
        e.Graphics.DrawLine(new Pen(Brushes.Black), 50, 50, Width - 100, Height - 100);

        //Required to tell me the framerate
        if ((DateTime.UtcNow - date).Seconds > 1)
        {
            date = DateTime.UtcNow;
            Debug.WriteLine(times);
            times = 0;
        }

        times++;
    }
Run Code Online (Sandbox Code Playgroud)

谢谢

史蒂夫〜

Han*_*ant 7

我的绘图卡在~65 FPS

是的,这是正常的.您正在测量操作系统的时钟中断率.在大多数Windows机器上,它每秒运行64次.计时器不能快于此,Interval属性的最小有用值为15.将其设置为1无效,它仍然只能每15.625毫秒滴答一次.

实际上,您可以提高中断率并使计时器的分辨率更好.你必须pinvoke timeBeginPeriod().然而,这是毫无意义的,人类无法观察到差异.然而,用户笔记本电脑上的电池会消耗得更快.

这里聪明的做法是使用实用的更新速率.人眼每秒上升到大约20帧,之后它变成模糊.或者看起来很流畅,具体取决于您正在进行的更新类型.在电影院中被利用的东西,它以24 fps更新.因此实际的Interval属性值略低于预期时钟中断率的倍数.其中2 x 15.625 = 31毫秒或32 fps.并且3 x 15.625 = 46毫秒或21 fps.您不希望随意使这些数字变小,如果您这样做,您的程序将不会在不同的计算机上具有一致的更新速率.

如果您的绘画代码无法跟上该速率,您只需要优化代码.只要你使用计时器并且不试图像你一直那样强迫加速,那么在慢速机器上实际上什么都不会出错.定时器的Tick事件将被延迟,您的有效FPS现在将由您的绘画代码的速度设置.

通过计算实际经过的时间而不是依赖于帧编号,可以避免动画序列在慢速机器上花费更长的时间.从Environment.TickCount或DateTime.UtcNow开始,它们也以时钟中断速率更新.秒表也没问题,这太过分了.然后动画将在快速机器上运行,它看起来会更粗糙.

  • “从Environment.TickCount或DateTime.UtcNow中获取”:我确实建议使用秒表代替。差异很小,但有时很明显。“人眼每秒可拍摄约20帧”:有针对运动而优化的传感器单元。这些速度超过20fps。“在电影院中,它以24 fps的速度更新”:您实际上看过一部具有24 fps刷新率的电影吗?闪烁是可怕的,使我头痛。这就是为什么监视器具有更高的刷新率以避免闪烁,而是连续显示同一图像多次的原因。 (2认同)
  • 闪烁与更新速率无关,它由投影产生.旧的CRT闪烁很多,因为它们具有持续时间非常短的快速荧光粉.液晶显示器正在到达那里.监视器由视频适配器的帧速率更新,完全独立于动画速率. (2认同)