【问题标题】:WPF Memory leak with derived TextBoxes派生文本框的 WPF 内存泄漏
【发布时间】:2011-09-01 14:34:44
【问题描述】:

在我的一个应用程序中,我遇到了无法解决的性能问题:

应用程序是使用派生自 TextBox 类的输入控件构建的,在 Themes\Generic.xaml 中有自己的 ControlTemplate。

我的问题是,这些控件在不再使用后不会被释放。如果我使用 SciTech MemoryProfiler 查看它们,我会发现它们由 System.Windows.Documents.TextEditor 的实例持有,TextEditor-instance 通过终结器队列持有。
内存分析器将警告附加到 TextEditor-instance,说“实例间接地由终结器队列根植”。
有人知道这里发生了什么吗?不允许直接从TextBox派生吗?还是我忘记了要实施的重要事项?

实施的其他信息:
其中一些派生控件的实现非常简单。在类构造函数中,DefaultStyleKeyProperty 的元数据被覆盖,并且没有事件处理程序附加到控件模板中包含的元素。比如:

public class MyDerivedTextBox : TextBox{

   static MyDerivedTextBox(){
       DefaultStyleKeyProperty.OverrideMetadata(typeof(MyDerivedTextBox), new FrameworkPropertyMetadata(typeof(MyDerivedTextBox)));
   }

}

(简化的)样式看起来像:

<Style TargetType="{x:Type myApp_controls:MyDerivedTextBox}">
     <Setter Property="SnapsToDevicePixels" Value="True"/>
     <Setter Property="UndoLimit" Value="1"/>
     <Setter Property="FocusVisualStyle" Value="{x:Null}"/>        
     <Setter Property="Template">
         <Setter.Value>
            <ControlTemplate TargetType="{x:Type myApp_controls:MyDerivedTextBox }">
                <Border Name="Border" ... >
                     <ScrollViewer Margin="1" x:Name="PART_ContentHost" />
                </Border>
          </Setter.Value>
      </Setter>
</Style>

【问题讨论】:

    标签: wpf wpf-controls profiling controltemplate


    【解决方案1】:

    终结器队列
    关于终结器队列的问题的答案是,观察到的效果不是恒定的:在我分析内存时,终结根本没有完成。这里的问题是了解我使用过的工具(和环境)。

    内存泄漏
    然而,泄漏本身是一个真正的问题,事实证明,它是the same thing 我也在其他位置(在同一个应用程序中)观察到。 绑定到未实现 INotifyPropertyChanged 的​​类的 CLR 属性http://support.microsoft.com/kb/938416/en-us

    这是我的第一个 WPF 项目之一,同时它成长为一个巨大的应用程序。在我开始的时候,我并不知道 WPF 在上面提到的绑定方面存在问题,并且在开发过程中我尝试尽可能多地使用数据绑定,但并不关心目标对象。现在,在应用程序变得如此庞大且客户端数量急剧增加之后,这些内存问题开始暴露(并导致非常奇怪的影响)。

    在解决了最有问题的绑定之后,终结器队列的效果也大大降低了。似乎之前,内存泄漏导致了对象终结的延迟执行(这只是一个假设,我没有深入研究 GC 行为)。

    派生文本框:
    我创建了一个带有此类派生文本框控件的小示例项目,并在内存分析器中的一些压力测试中使用它们。据我对测试项目的观察可以说,从 TextBoxes 派生,因为我做得很好。

    法兹特
    我只能强调在应用程序创建过程中检查 Bindings 的目标对象的重要性。否则,识别应用程序中的泄漏点将是大量工作。我希望这个解释可以帮助那些没有像我一样犯过同样错误的人。

    【讨论】:

      【解决方案2】:

      不确定它是否会改变任何东西,但不是您控件中的静态构造函数,您是否尝试过类似的东西:

      public MyDerivedTextBox() 
      {
        this.DefaultStyleKey = typeof(MyDerivedTextBox);
      }
      

      这是我比较熟悉的模式。也许 MetaDataOverride 正在做一些奇怪的事情。

      顺便说一句,我确实注意到一些 Silverlight 内存问题,是 Tablet PC Input Services 带来了无法解释的 AutomationPeers(请参阅 http://www.wintellect.com/CS/blogs/sloscialo/archive/2011/04/13/silverlight-memory-leaks-and-automationpeers.aspx)。

      【讨论】:

      • +1 感谢您的回答。最后,这是我在另一个位置已经遇到的问题:DataBindings 到既不实现 INotifiyPropertyChanged 也不从 DependencyObject 派生的对象的属性。在我开始这个项目时,我不知道这在大型项目中会有多糟糕。对于从 TextBoxes 的派生,我现在可以肯定地说这很好。
      猜你喜欢
      • 2017-03-01
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      • 2011-02-21
      • 1970-01-01
      • 2010-12-05
      相关资源
      最近更新 更多