【问题标题】:WPF canvas performance- children.add called many timesWPF画布性能-children.add多次调用
【发布时间】:2011-01-31 00:07:18
【问题描述】:

我在长画布上画了很多线(想想条形图),并对其进行了相当好的性能调整,使用低级几何类并冻结它们等。这显着提高了性能,但仍然需要几秒钟将几千个项目加载到画布中。我对应用程序进行了性能分析,看起来每次调用canvas.children.add() 都花费了很大一部分时间。我已经读过这应该是一个轻量级的调用,并且由于我在一个方法中多次调用它,它不应该尝试在两者之间做任何繁重的事情......这可能还有其他原因吗如此多的时间?有什么办法可以加快速度吗?

性能并不差,但我担心以后当我需要处理更大的数据集时它可能会成为更大的问题。

仅供参考,在此示例中它看起来被调用了 1400 次,并且在现代/快速笔记本电脑上占用了将近 3 秒的 CPU 时间。

虽然画布包含在其他控件的层次结构中,所以我很好奇它们是否可能对此有所贡献。

额外说明:我也没有在画布上设置特定高度,因为它被设置为填充网格父容器。这可能是问题的根源吗?

【问题讨论】:

  • 就性能而言,您可以尝试msdn.microsoft.com/en-us/library/… Stream Geometry,它是比绘图上下文最轻量级的构造。
  • 是的,已经在使用流几何,并且效果很好。谢谢

标签: c# .net wpf canvas


【解决方案1】:

主要问题是 Children.Add 始终是一个缓慢的操作,即使您使用 StreamGeometry 对象。我最近遇到了同样的问题并得出以下结论: 如果将一堆对象放入一个新的画布中,并嵌套到主画布中,加法操作的性能将大大提高。 因此,不要添加 1400 个元素,而是将 200 个元素放在 7 个画布中,然后将这 7 个画布添加到主画布中。 由于现在所有对象都属于不同的画布,因此您需要稍微调整一下您的应用程序,但与迁移到像 DrawingVisual 这样的替代解决方案相比,这将是一个不那么激烈的解决方案

【讨论】:

  • Jaime,您估计从中获得多大的性能增益?即 10% 或 100% 速度增益?谢谢。
  • 在我的具体情况下(一次添加 300 个对象超过 5000 多个子集合),我有 2.5 秒的延迟,变成了 0.3 秒。
  • 我发现我实际上使用的是路径几何而不是流,所以刚刚完成转换 - 现在肯定更快,但可能仍然超过一秒钟。所以现在我会在时间允许的情况下尝试分割​​画布。
  • 我很好奇您是否尝试将多个画布放入堆栈面板而不是父画布?会更容易弄清楚定位等,但主要是好奇这是否有助于或损害性能。
  • 我没有尝试过使用 stackpanel。这对我来说没有意义,因为子画布将被放置在不同的位置。使用父画布,所有子画布都可以相互叠加,因此内部的对象将有一个共同的坐标系。
【解决方案2】:

只是添加关于画布所在控件的层次结构,以及画布的高度:

Canvas 总是占用与其给定的空间一样多的空间,并且无论您添加什么孩子 - 它都不会触发其父母的新 Measuer/Arrange 传递。因此,无论您在画布内做什么,都不会影响它所包含的视觉树。 总结一下 - 问题不能来自那里,关于 StreamGeomatry 的建议是完全正确的 - 这就是导致你出现性能问题的原因,切换到 streamgeormatry 可以解决它。

【讨论】:

  • 我已经在为所有适用的添加子代使用流几何。它们确实对性能有很大帮助,但仍希望大幅提高。
  • 骗了我——我实际上在某个时候使用了路径几何。刚刚转换为streamgeo,肯定更快。
【解决方案3】:

我建议您将形状直接绘制到图像中,而不是将它们添加为子对象。 渲染孩子有巨大的开销(如您所见)。

参考一些有用的文章有一个类似的问题:

How to draw line of ten thousands of points with WPF within 0.5 second?

【讨论】:

  • 希望避免这种情况,因为我还有其他事情要做,这可能会使总是重绘变得复杂。例如,顶部添加的文本框和图像是可拖动的,并且该部分很长,因此存在于可滚动的容器中。很多变量需要考虑...
  • 根据性能对您的重要性,您可能需要考虑在 C# 中的众多游戏框架之一中使用解决方案(即操作精灵的东西)。当然 - 如果你还想使用其他对你没有帮助的 UI 框架机制......顺便说一句:在某些情况下 WPF 不会使用硬件渲染,这会大大降低性能 - 你可以用这个方法来检查它 'Debug .WriteLine("WPF RenderCapabilities: Rendering Tier = " + (RenderCapability.Tier >> 16) + " (Desired 2, 0 表示没有硬件加速)");'
猜你喜欢
  • 1970-01-01
  • 2015-08-30
  • 1970-01-01
  • 2016-01-04
  • 1970-01-01
  • 2020-06-08
  • 2014-09-07
  • 1970-01-01
  • 2015-01-28
相关资源
最近更新 更多