使用大量控件调整窗口大小时的WPF性能问题

时间:2022-09-01 19:16:03

I have a WPF window that contains a fancy image with roughly 200 controls (derived from buttons), all of which use one of my 5 templates (paths, shadow effects, etc). Agreed, it is a heavy window to draw. I can live with that.

我有一个WPF窗口,其中包含一个花式图像,大约有200个控件(从按钮派生),所有这些都使用我的5个模板中的一个(路径,阴影效果等)。同意,这是一个沉重的窗口。我可以忍受这一点。

My problem comes from resizing the window. Maximize/Restore take about 1-2 seconds, but manually dragging the bottom-left corner causes the system to hang for about 5-10 seconds. In that delay, the window is black & contains partial leftovers until the final result is shown. It looks amateurish and that, I can't live with.

我的问题来自调整窗口大小。最大化/恢复大约需要1-2秒,但手动拖动左下角会导致系统挂起约5-10秒。在该延迟中,窗口为黑色并包含部分剩余部分,直到显示最终结果。它看起来很业余,我不能忍受。

Remote connection : using a remote account, I found that the window resize always takes 1-2 seconds, but doesn't draw the "intermediate" stages while I'm dragging the window borders. The result is as snappy as I would expect.

远程连接:使用远程帐户,我发现窗口调整大小总是需要1-2秒,但在拖动窗口边框时不会绘制“中间”阶段。结果像我期望的那样快活。

My conclusion is this: It's the redraws during the resize that are bottlenecks.

我的结论是:调整大小期间的重绘是瓶颈。

The inevitable question is this : how can I prevent redrawing the window until the resize is finished?

不可避免的问题是:如何在重新调整大小之前阻止重绘窗口?

Thanks in advance for any ideas...

提前感谢任何想法......

3 个解决方案

#1


4  

@Seb: I'm beginning to think WPF is not designed for interfaces that go beyond 2-3 controls at a time

@Seb:我开始认为WPF不适用于一次超过2-3个控件的接口

Visual Studio 2010 and Expression Blend should be good counterexamples. Though Visual Studio sometimes freezes the bottleneck is definitely not in the WPF rendering.

Visual Studio 2010和Expression Blend应该是很好的反例。虽然Visual Studio有时会冻结瓶颈,但绝对不是WPF渲染。

@Seb: The inevitable question is this : how can I prevent redrawing the window until the resize is finished?

@Seb:不可避免的问题是:如何在重新调整大小之前阻止重绘窗口?

Simply set the window's content visibility to Visibility.Collapsed before the resize/maximize and make it visible afterwards. Though I think you asked the wrong question. Here is the right one

在调整大小/最大化之前,只需将窗口的内容可见性设置为Visibility.Collapsed,然后使其可见。虽然我认为你问了错误的问题。这是正确的

How to make my controls measure/arrange extremely fast?

如何使我的控件测量/安排非常快?

And to answer it you should take a look at your code. Maybe you intensively use dependency properties in the measuring/arrange algorithm? Or maybe you picked wrong panels (e.g. Grid is slower than Canvas)? Or maybe... I stop guessing here :).

要回答它,你应该看看你的代码。也许您在测量/排列算法中集中使用依赖属性?或者您可能选择了错误的面板(例如Grid比Canvas慢)?或许......我在这里停止猜测:)。

By the way, it's always better to launch your app under profiler and prove the bottleneck rather than assuming the place where it might be. Check Eqatec Profiler it's free yet powerful enough. VS 2010 also offers nice profiling features, though it's far from being free. And you may want to check WPF Performance Suite.

顺便说一句,最好是在profiler下启动你的应用程序并证明瓶颈而不是假定它可能存在的位置。检查Eqatec Profiler它是免费但功能强大。 VS 2010还提供了很好的分析功能,但它远非免费。您可能想要检查WPF Performance Suite。

Hope this helps.

希望这可以帮助。

#2


1  

Let me know how this works... I am assuming that your root visual item is stretching to horizontally and vertically to fill your window with auto height/width. Get rid of the Auto height/width. On app start up set the dimensions of the root element. There is a FrameworkElements have a size changed event. Register for this on your Application.Current.MainWindow (maybe be a typo, that was from memory). Whenever this event fires, start a timer with a small interval. If you get another resize while the timer is running, ignore it and reset the timer. Once the timer fires, you now know the new size the user desires and that they have (at least for a short period) stopped resizing the window.

让我知道这是如何工作的......我假设您的根视觉项目是水平和垂直拉伸,以自动高度/宽度填充窗口。摆脱自动高度/宽度。在应用启动时设置根元素的尺寸。有一个FrameworkElements有一个大小改变的事件。在您的Application.Current.MainWindow上注册此内容(可能是一个错字,来自内存)。每当此事件触发时,以较小的间隔启动计时器。如果在计时器运行时再次调整大小,请忽略它并重置计时器。一旦计时器触发,您现在知道用户期望的新大小,并且他们(至少在短时间内)停止调整窗口大小。

Hope that helps!

希望有所帮助!

#3


0  

From Ragepotato's answer and your comment about needing to see roughly what the interface would look like while resizing, as long as you don't have your objects dynamically re-locating themselves (like a Wrap Panel) - you could take a screenshot of the window contents and fill your frame with it.
Set it to stretch both height and width, and you'd get a (slightly fuzzy) idea of what a particular size would be. It wouldn't be live while resizing, but for those few seconds that probably wouldn't matter..

从Ragepotato的回答和你的评论中看到,只要你没有动态地重新定位自己的对象(比如一个Wrap Panel),你需要大致看看界面在调整大小时的样子 - 你可以截取窗口的截图内容并用它填充你的框架。将它设置为拉伸高度和宽度,你会得到(稍微模糊)一个特定尺寸的概念。调整大小时不会生效,但对于那些可能无关紧要的几秒钟。

#1


4  

@Seb: I'm beginning to think WPF is not designed for interfaces that go beyond 2-3 controls at a time

@Seb:我开始认为WPF不适用于一次超过2-3个控件的接口

Visual Studio 2010 and Expression Blend should be good counterexamples. Though Visual Studio sometimes freezes the bottleneck is definitely not in the WPF rendering.

Visual Studio 2010和Expression Blend应该是很好的反例。虽然Visual Studio有时会冻结瓶颈,但绝对不是WPF渲染。

@Seb: The inevitable question is this : how can I prevent redrawing the window until the resize is finished?

@Seb:不可避免的问题是:如何在重新调整大小之前阻止重绘窗口?

Simply set the window's content visibility to Visibility.Collapsed before the resize/maximize and make it visible afterwards. Though I think you asked the wrong question. Here is the right one

在调整大小/最大化之前,只需将窗口的内容可见性设置为Visibility.Collapsed,然后使其可见。虽然我认为你问了错误的问题。这是正确的

How to make my controls measure/arrange extremely fast?

如何使我的控件测量/安排非常快?

And to answer it you should take a look at your code. Maybe you intensively use dependency properties in the measuring/arrange algorithm? Or maybe you picked wrong panels (e.g. Grid is slower than Canvas)? Or maybe... I stop guessing here :).

要回答它,你应该看看你的代码。也许您在测量/排列算法中集中使用依赖属性?或者您可能选择了错误的面板(例如Grid比Canvas慢)?或许......我在这里停止猜测:)。

By the way, it's always better to launch your app under profiler and prove the bottleneck rather than assuming the place where it might be. Check Eqatec Profiler it's free yet powerful enough. VS 2010 also offers nice profiling features, though it's far from being free. And you may want to check WPF Performance Suite.

顺便说一句,最好是在profiler下启动你的应用程序并证明瓶颈而不是假定它可能存在的位置。检查Eqatec Profiler它是免费但功能强大。 VS 2010还提供了很好的分析功能,但它远非免费。您可能想要检查WPF Performance Suite。

Hope this helps.

希望这可以帮助。

#2


1  

Let me know how this works... I am assuming that your root visual item is stretching to horizontally and vertically to fill your window with auto height/width. Get rid of the Auto height/width. On app start up set the dimensions of the root element. There is a FrameworkElements have a size changed event. Register for this on your Application.Current.MainWindow (maybe be a typo, that was from memory). Whenever this event fires, start a timer with a small interval. If you get another resize while the timer is running, ignore it and reset the timer. Once the timer fires, you now know the new size the user desires and that they have (at least for a short period) stopped resizing the window.

让我知道这是如何工作的......我假设您的根视觉项目是水平和垂直拉伸,以自动高度/宽度填充窗口。摆脱自动高度/宽度。在应用启动时设置根元素的尺寸。有一个FrameworkElements有一个大小改变的事件。在您的Application.Current.MainWindow上注册此内容(可能是一个错字,来自内存)。每当此事件触发时,以较小的间隔启动计时器。如果在计时器运行时再次调整大小,请忽略它并重置计时器。一旦计时器触发,您现在知道用户期望的新大小,并且他们(至少在短时间内)停止调整窗口大小。

Hope that helps!

希望有所帮助!

#3


0  

From Ragepotato's answer and your comment about needing to see roughly what the interface would look like while resizing, as long as you don't have your objects dynamically re-locating themselves (like a Wrap Panel) - you could take a screenshot of the window contents and fill your frame with it.
Set it to stretch both height and width, and you'd get a (slightly fuzzy) idea of what a particular size would be. It wouldn't be live while resizing, but for those few seconds that probably wouldn't matter..

从Ragepotato的回答和你的评论中看到,只要你没有动态地重新定位自己的对象(比如一个Wrap Panel),你需要大致看看界面在调整大小时的样子 - 你可以截取窗口的截图内容并用它填充你的框架。将它设置为拉伸高度和宽度,你会得到(稍微模糊)一个特定尺寸的概念。调整大小时不会生效,但对于那些可能无关紧要的几秒钟。