什么是避免WPF PRISM/MVVM应用程序中的内存泄漏的最佳方法

Ian*_*kes 13 wpf memory-leaks prism mvvm

我有一个基于PRISM的WPF应用程序,它使用MVVM模式.

我注意到偶尔我的视图模型,视图以及与它们相关的所有内容将在其预期寿命之后很久就会出现问题.

一个泄漏涉及在属于注入服务的集合上订阅CollectionChanged,另一个涉及不在DispatcherTimer上调用Stop方法,而另一个泄漏需要清除它的项目.

我觉得使用CompositePresentationEvent可能比订阅CollectionChanged更可取,但在其他场景中,我倾向于实现IDisposable并让视图在视图模型上调用Dispose方法.

但是后来需要告诉视图什么时候在视图模型上调用Dispose,当视图的复杂性增加时,它会变得更具吸引力,并且它们开始包含子视图.

您认为处理视图模型的最佳方法是什么,以确保它们不会泄漏内存?

提前致谢

伊恩

And*_*mes 14

我可以告诉你,我经历过100%的痛苦.我想,我们是内存泄漏兄弟.

不幸的是,我在这里想到的唯一一件事与你的想法非常相似.

我们所做的是创建一个附加属性,视图可以应用于自身以将处理程序绑定到ViewModel:

<UserControl ...
             common:LifecycleManagement.CloseHandler="{Binding CloseAction}">
...
</UserControl>
Run Code Online (Sandbox Code Playgroud)

然后我们的ViewModel只有一个Action类型的方法:

public MyVM : ViewModel
{
     public Action CloseAction
     {
          get { return CloseActionInternal; }
     }

     private void CloseActionInternal()
     {
          //TODO: stop timers, cleanup, etc;
     }
}
Run Code Online (Sandbox Code Playgroud)

当我的close方法触发时(我们有几种方法可以做到这一点......它是TabControl UI,标签标题上有"X",那种事情),我只是检查这个视图是否已经使用AttachedProperty注册了自己.如果是这样,我调用那里引用的方法.

这是一个非常迂回的方式,只需检查一下View的DataContext是否是IDisposable,但当时感觉更好.检查DataContext的问题是您可能有需要此控件的子视图模型.你要么必须确保你的viewmodels链接这个dispose调用或检查图中的所有视图,看看他们的datacontexts是否是IDisposable(呃).

我有点觉得这里缺少一些东西.还有一些其他框架试图以其他方式缓解这种情况.你可以看看Caliburn.它有一个处理这个的系统,其中ViewModel知道所有子视图模型,这使它能够自动链接事物.特别是,有一个名为ISupportCustomShutdown的接口(我认为这就是它所称的)有助于缓解这个问题.

但是,我所做的最好的事情是确保使用Redgate Memory Profiler等良好的内存泄漏工具,帮助您可视化对象图并找到根对象.如果您能够识别DispatchTimer问题,我想您已经在做这个了.

编辑:我忘记了一件重要的事情.由DelegateCommand中的一个事件处理程序引起的潜在内存泄漏.这是关于Codeplex的一个线程解释它.http://compositewpf.codeplex.com/WorkItem/View.aspx?WorkItemId=4065

最新版本的Prism(v2.1)已经修复了这个问题.(http://www.microsoft.com/downloads/details.aspx?FamilyID=387c7a59-b217-4318-ad1b-cbc2ea453f40&displaylang=en).