3

我在我的应用程序中遇到了性能问题。本质上,我单击一个按钮,列表中填充了数据绑定数据(由于大量数据,这是虚拟化的),然后单击另一个按钮,该按钮将向关联的列表视图中添加一行。我之所以含糊不清,是因为我认为有必要说明 UI 中实际发生的事情有多么少。

这是我所知道的:

  • 我在运行 Win 7 Pro 的强大开发计算机上,也没有在具有不错规格的 XP SP3 机器上看到这个问题。我只在运行 Win 7 企业版、4 GB RAM 和 Core i5 CPU(比 XP 台式机强大得多)的特定品牌笔记本电脑(联想 ThinkPad)上看到它。
  • 由于上述发现,我不认为这是代码问题。
  • 我使用 Microsoft 的 PerfView 工具进行了分析,并注意到我认为对 UIElement.Measure 的大量调用(我们的代码从未直接调用过),这是我在其他机器上分析时看不到的。
  • 笔记本电脑的分辨率为 1360x780,所以我认为可能是小分辨率导致 GPU 不必要地渲染控件,因为我可能正在执行一些数据绑定(这可能解释了对 Measure() 的大量调用)。我将笔记本电脑的显示屏扩展到我的 24 英寸显示器,但没有看到任何改进。

现在我假设问题出在 GPU 上。我已经更新了驱动程序,没有任何改进。

  1. 即使我认为这不是代码问题,是否有相当于“SuspendLayout()”的WPF
  2. 有没有办法分析 GPU 性能以查看它是否在某些过程中受到锤击
  3. (远景)有没有人遇到过类似的性能问题,似乎是特定于计算机的,以及如何追踪它们的建议?

对不起,如果这是一个模糊的问题。我试图使其符合 SO 的使用要求。如果您想了解更多信息,请告诉我。

就像附录一样:该程序使用的是 WPF,C# 4.0,问题似乎与 Telerik 控件有关(尽管我不认为它们是可疑的,因为我们在其他地方使用它们没有问题)。

4

2 回答 2

2

原来它是由一个已知​​的微软问题引起的。我会试着解释,但我不会。主要是我做不到。

关于修复的文章(参见 Viðar 于 2010 年 8 月 3 日发布的帖子):

Microsoft 修补程序站点:http: //support.microsoft.com/kb/2484841/en-us

修复: http: //archive.msdn.microsoft.com/KB2484841/Release/ProjectReleases.aspx? ReleaseId=5583

于 2013-02-25T19:24:27.607 回答
1

1.回答

为了防止MeasureOverride来自 WPF 的猖獗调用ContextLayoutManager

protected override void OnChildDesiredSizeChanged(UIElement el)
{
    /* base.OnChildDesiredSizeChanged(el); */       // avoid rampant remeasuring
}

2.相关引用

UIElement.OnChildDesiredSizeChanged(UIElement) Method
  ...

OnChildDesiredSizeChanged(UIElement)方法具有调用InvalidateMeasure()自身的默认实现。一个典型的实现是:做你自己的元素支持的任何优化,然后通常OnChildDesiredSizeChanged(UIElement)从代码分支的a̲t̲ l̲e̲a̲s̲t̲ o̲n̲e̲调用 base ...

...这意味着(和事实)是,对于由其任何一个子级发起的任何单个父级布局传递,父MeasureOverride级将被额外调用一次 - 并且可能是额外的 - 为其每个子级调用一次尺寸也发生了变化。

3. 讨论

在多个孩子“同时”改变他们的大小的情况下,父母通常会在第一次调用期间完全检测并考虑所有孩子之间的新整体布局。这是WPF中的标准做法,并且通过故意排除某些特定触发子项的任何指示来鼓励。除了在最常见的情况下没有这样的孩子(有关详细信息,请参见上面的链接)这一事实之外,它还使尝试任何类型的“部分布局”的代码变得繁琐。但大多数情况下,为什么在没有首先获得所有最新可用测量值的情况下进行任何布局计算?MeasureOverride(…)

所以我们看到,在一个MeasureOverride调用之后,由恰好是“第一个”的任何一个孩子触发(这不重要),父母的布局实际上应该是关于其所有最新的孩子大小信息的最终布局。但这并不意味着任何排队OnChildDesiredSizeChanged的通知——对于其他大小也发生了变化的孩子——已经消失了。这些调用仍在父进程中等待处理,除非明确放弃虚拟基本调用(如项目符号 #1 所示),否则每个调用都会生成一个额外的、现在无关的MeasureOverride调用。

4. 警告

此处显示的代码禁用a̲l̲l̲子发起的度量无效,这适用于父母故意禁止此类更改或天生就已经知道它们的情况。这并不少见;例如,它包括任何始终完全确定和强制其子级大小的父级,或更一般地,任何仅DesiredSize在其自己的度量传递期间采用其子级的值的父级。重要的是仅由其自己的父级充分保证对父级的测量。

父母可能希望取消一些儿童发起的措施通知而保留/允许其他通知的情况自然将取决于其他特定情况。看起来比较晦涩,这里就不一一赘述了。

于 2021-04-12T21:56:17.460 回答