为什么在Windows 10的后台线程中运行控件时,我不能在WPF应用程序中获得60帧/秒的流畅动画?

本文关键字:60帧 应用程序 动画 WPF 线程 后台 Windows 运行 控件 为什么 不能 | 更新日期: 2023-09-27 18:12:52

我试图在后台线程中托管一个控件,这样它就可以以恒定的60 FPS显示动画,即使UI线程被阻塞。这在Windows 8.1中工作得很好,但升级到Windows 10后就失败了。

我钩子了CompositionTarget。从承载控件的后台线程呈现事件,以便动画可以与监视器刷新同步。但是,似乎只要主UI线程中的某些东西也挂钩到渲染事件,每当主UI线程中托管的视觉变化时,帧就会被跳过。

我可以直观地看到帧被跳过,根据RenderingEventArgs类中暴露的RenderTime,这证实了帧被跳过,因为从最后一帧开始的时间增量大约是33ms,而不是每次帧跳过时的16ms。

可以通过钩接CompositionTarget来触发跳转。在UI线程中渲染事件而在事件处理程序中什么都不做,或者通过启动storyboard动画,我猜这是因为storyboard动画挂钩了CompositionTarget。渲染事件实现平滑动画。

下面是一个简单的示例项目,它演示了这个问题:

SmoothAnimationTest.zip

我在Windows 8.1和Windows 10的几台机器上测试了它,在任何情况下,Windows 8.1在"自己的线程"控制下都能以60帧/秒的速度运行。在Windows 10中,"显示抖动1"将帧率降低到恒定的30 FPS,而"显示抖动2"会导致帧率在30和60 FPS之间不规律地切换,平均约为45-50。

在Windows 8.1和Windows 10中,按下'Block UI Thread'按钮可以在单独的线程控制中实现60 FPS的平滑运行。

一个解决方案是让动画在UI线程中运行,并从该线程中删除所有阻塞代码,不幸的是,这不是一个简单的任务,因为我正在处理的应用程序很复杂,并且有许多地方UI可以阻塞超过几毫秒,这可能导致动画中的抖动

为什么在Windows 10的后台线程中运行控件时,我不能在WPF应用程序中获得60帧/秒的流畅动画?

这可能不是一个完整的答案,但我认为最好不要把它写成评论。

首先,你是否验证了这个问题不是。net 4.6的问题?Win 10发布的。net 4.6取代了Win 8.1发布的。net 4.5, . net 4.6包含了相当多的内部变化和新的bug。我会在Win 8.1上安装。net 4.6来验证这是我的第一步…(如果这个bug是。net 4.6的,那么你必须通过Connect报告,但不要抱太大希望。这个bug可能需要几年的时间才能修复,如果可以的话)

其次,我不知道你是怎么控制的,但听起来你需要另一个调度员。但这需要另一个窗口。这样,无论主窗口发生了什么,都不会影响辅助窗口。

就像我说的,我不知道这个选项在你的情况下是否可行。可以让第二个窗口无边框,最上面,并与第一个窗口重叠…