我尝试在后台线程中托管一个控件,这样即使UI线程被阻塞,它也可以以恒定的60FPS显示动画。这在Windows8.1中运行得很好,但由于升级到Windows10,它现在失败了。
我从托管控件的后台线程挂接CompositionTarget.Rendering事件,以便动画可以与监视器刷新同步。但似乎只要主UI线程中的某些内容也挂接到呈现事件,只要主UI线程中托管的视觉发生更改,帧就会被跳过。
我可以直观地看到被跳过的帧,根据RenderingEventArgs类中公开的RenderTime,这证实了帧正在被跳过,因为无论何时发生帧跳过,从最后一帧开始的时间增量大约是33ms而不是16ms。
跳过可以通过在UI线程中挂钩CompositionTarget.Rendering事件并在事件处理程序中什么也不做,或者通过启动故事板动画来诱导,我猜这是因为故事板动画挂钩CompositionTarget.Rendering事件来实现平滑动画。
下面是一个简单的示例项目,它演示了这个问题:
我在Windows8.1和Windows10的几台机器上测试了它,在每种情况下,Windows8.1都可以完美地运行在“自己的线程”控件上,无论如何,它的运行速度都是60FPS。在Windows 10中,“显示抖动1”将帧速率降低到恒定的30 FPS,而“显示抖动2”会导致帧速率在30到60 FPS之间不稳定地切换,平均约为45-50。
在Windows 8.1和Windows 10中,按下“阻止UI线程”按钮会在单独的线程控件中产生平滑的60 FPS。
一种解决方案是让动画在UI线程中运行,并从该线程中删除所有阻塞代码,不幸的是,这不是一个简单的任务,因为我正在处理的应用程序很复杂,并且在许多地方UI可能会阻塞超过几毫秒,这可能会导致动画中的抖动。
发布于 2016-02-28 18:29:01
这可能不是一个完整的答案,但我认为最好不要把它写成评论。
首先,您是否验证了问题不是与.Net 4.6有关?Win 10附带.Net 4.6,取代了Win 8.1附带的.Net 4.5。.Net 4.6包含了相当多的内部更改和新的错误。我会在Win8.1上安装.Net 4.6来验证这一点,作为我的第一步…(如果错误是.Net 4.6的,那么你必须通过Connect报告它,但不要抱太大希望。可能需要数年时间才能修复bug (如果根本没有修复的话)
其次,我不确切地知道你是如何显示你的控件的,但是听起来你需要一个second dispatcher。不过,这将需要另一个窗口。这样,无论主窗口上发生了什么,都不会影响辅助窗口。
正如我所说的,我不知道此选项在您的方案中是否可行。可以使第二个窗口无边框,最上面,并与第一个窗口重叠。
https://stackoverflow.com/questions/32585842
复制相似问题