【问题标题】:how to make DispatcherTimer events smoother in WPF?如何使 WPF 中的 DispatcherTimer 事件更流畅?
【发布时间】:2013-01-16 09:02:45
【问题描述】:

在我的 WPF 应用程序中,用户按下按钮以启动 3D 模型平滑旋转,然后松开按钮以停止旋转。

为此,我创建了一个 DispatcherTimer:

DispatcherTimer timer = new DispatcherTimer();
timer.Tick += new EventHandler( timer_Tick );
timer.Interval = new TimeSpan( 0, 0, 0, 0, 30 );

当按下按钮时我调用timer.Start(),当松开按钮时我调用timer.Stop()

timer_Tick 函数改变模型的旋转:

    void timer_Tick( object sender, EventArgs e )
    {
        spin = ( spin + 2 ) % 360;
        AxisAngleRotation3D rotation = new AxisAngleRotation3D( new Vector3D( 0, 1, 0 ), spin );
        Transform3D rotate = new RotateTransform3D( rotation );
        model2.Transform = rotate;
    }

我注意到,模型大部分时间都在平稳旋转,但经常冻结和卡顿,停顿的时间不同,有时长达 1/4 秒。

有没有办法让它更流畅?我知道通过使用 DispatcherTimer(而不是 System.Timers.Timer),回调发生在 UI 线程上。但我必须在 UI 威胁下才能运行线路

        model2.Transform = rotate;

我已经阅读了有关在其他线程上获取计时器回调的各种方法。但似乎最终我必须与 UI 线程同步才能调用该行。如果我使用 Invoke() 将 System.Timers.Timer 回调线程编组到 UI 线程,这会带来整体更流畅的动画吗?似乎不应该,因为它必须与 UI 线程同步,就像 DispatcherTimer 可能所做的那样。就此而言,对于 UI 线程而言,似乎 任何 定期设置 model2.Transform 的方案都在同一条船上,不是吗?

(作为一个可能是次要的问题,我首先试图了解导致暂停的原因。据我所知,UI 线程正在做的其他事情没有什么重要的。所以我不明白是什么在这些暂停期间发生。垃圾收集?看起来不应该收集太多垃圾,而且暂停似乎不会那么极端。)

【问题讨论】:

  • 我认为您可以使用 model2.Dispatcher.BeginInvoke(new Action(() => { model2.Transform = rotate; })) 在 model2 父线程中调用它
  • 您似乎知道,通过使用替代计时器,您需要分派回 UI 线程,那么为什么要问这样做是否会产生更好的结果呢?你试过了吗?
  • 你想旋转什么样的物体?有可能是一些视觉元素,例如阴影或不透明蒙版,导致渲染性能不佳...
  • @acrilige 和 Daniel Kelly:我使用上面显示的 BeginInvoke() 行 acrilige 和常规计时器,它实际上提供了平滑的旋转。 Henk 在下面的回答对我仍然有用,因为它有助于表明 DispatchTimer 本身的优先级,而不是与 UI 线程本身同步,导致了卡顿。
  • 我知道它已经很老了,但如果有人偶然发现这个问题 - 我建议改用 Storyboard。我们在这里看到的不是 WPF 进行渲染转换的方式。我想知道它是如何工作的。

标签: c# wpf timer smooth dispatchertimer


【解决方案1】:

设置priority。默认值为Background,这可能解释了您看到的口吃。我认为Render 是您想要的级别,但请进行实验。

DispatcherTimer timer = new DispatcherTimer(DispatcherPriority.Render);

如果不够流畅,您可以尝试将其设置为动画。

【讨论】:

  • 它有效。感谢您提供简单的解决方案。当 DispatcherTimer 的优先级较低时,我仍然想了解在这些暂停期间发生了什么。框架只是决定让 DispatcherTimer 饿一段时间?为什么?它在忙什么?
  • @MKatz 我怀疑 Windows 在调用你的计时器之前会先处理应用程序消息队列中的任何消息
猜你喜欢
  • 1970-01-01
  • 2017-03-02
  • 2021-02-05
  • 1970-01-01
  • 2014-10-30
  • 1970-01-01
  • 2015-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多