2009-08-14 84 views
0

我在WPF/MVVM中绑定到ObservableCollection顶部的ItemsSource的TabControl。每个选项卡都有自己的集合,并与组件(如图像,Richtextbox和用户输入框)进行绑定,并且一切看起来都很顺利。WPF RichTextBox选项卡选择吃掉系统内存!

但是,我注意到,每次切换选项卡时,它都会使用大约100k的系统内存,而这些内存永远不会被回收!如果我按住ctrl-tab循环所有选项卡,我可以在一分钟内用完200兆内存。

现在我创建了一个空白WPF应用程序,只有一个选项卡控件,并且它还为每个选项卡开关使用内存(albiet很少)。这只是一些.NET错误或功能?也许它存储面包屑痕迹,也许它用于调试(虽然我编译在发布模式)。

我该如何回收我的记忆?或者更好的是,不要失去记忆切换标签?

回答

0

很好的建议,但最终我决定一个可绑定的文本块比richtextbox更有用和更简单。我从来没有发现是什么导致了泄漏 - 但它肯定是在bindablerichtextbox代码中(每次切换标签时都会调用OnInitialized,这超出了我的控制范围)。

泄漏消失了,我的应用运行更快,因为使用了更简单的可绑定文本块。

1

您可能想检查是否有任何事件处理程序被遗留。

如果您在其他控制中注册了某个事件,garbadge收集器将不会收集不再需要的对象,因为事件仍然可以这样说。

所以,如果你注册代码的某个地方加载背后

public ParentEditor() 
{ 
    InitializeComponents(); 
    control.Loaded += OnControlLoaded; 
} 

或XAML或ParentControl

<Control Loaded="OnControlLoaded" /> 

您basicly有两个解决方案来解决这个问题:

解决方案1 - 删除不再需要的事件处理程序:

您可能要在卸载像这样父控件删除此处理程序:

public ParentEditor() 
{ 
    InitializeComponents(); 
    control.Loaded += OnControlLoaded; 

    this.Unloaded += OnParentUnloaded; 
} 

void OnParentUnloaded(object sender, RoutedEventArgs e) 
{ 
    //Remove unloaded event 
    this.Unloaded -= OnParentUnloaded; 

    //Remove event from child control 
    control.Loaded -= OnControlLoaded;   
} 

您还可以使用过程中的子控件的空载情况下..这是给你..

解决方案2 - 使用WeakEvent模式:

事件另一种解决方案将是WeakEvent图案,它绕过这个问题。

为什么要实现WeakEvent模式?

聆听事件可能导致内存泄漏 。用于收听事件的典型技术 是使用 将处理程序附加到 源上的事件的语言特定语法。例如,在C#中, 的语法是:source.SomeEvent + = new SomeEventHandler(MyEventHandler)。

此技术创建从事件源到 事件侦听器的强引用 。通常,为听众附加一个事件处理程序 会导致 收听者有一个对象 影响对象的生命周期(除非明确地删除了 事件处理程序)。 但在某些情况下,你可能 希望被其他 因素,如是否 目前属于该应用程序的可视化树 ,而不是由 一生源的唯一控制的 监听的对象的生命周期。每当源对象的生命周期超出 时,监听器的对象生存期, 正常事件模式导致内存泄漏:监听器保持 比预期长。

在这两种情况下,好运 ..其很难找到像您所遇到的一个泄漏!

+0

谢谢你的建议 - 非常有用!但是对于MVVM,甚至不使用事件处理程序。 viewmodel对gui一无所知,只是公开gui挂钩的命令。 – bluebit 2009-08-17 09:36:40