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

标签 wpf mvvm memory-leaks prism

我有一个基于 PRISM 的 WPF 应用程序,它利用了 MVVM 模式。

我注意到有时我的 View 模型、 View 以及与它们相关的所有东西都会在它们的预期生命周期之后很长一段时间内徘徊。

一个泄漏涉及在属于注入(inject)服务的集合上订阅 CollectionChanged,另一个涉及不调用 DispatcherTimer 上的 Stop 方法,还有一个需要清除集合中的项目。

我觉得使用 CompositePresentationEvent 可能比订阅 CollectionChanged 更可取,但在其他情况下,我倾向于实现 IDisposable 并让 View 调用 View 模型上的 Dispose 方法。

但是接下来需要告诉 View 何时在 View 模型上调用 Dispose,当 View 的复杂性增加并且它们开始包含 subview 时,这变得更不吸引人了。

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

提前致谢

伊恩

最佳答案

我可以告诉你,我已经经历了你所经历的 100% 的痛苦。我想我们是内存泄漏兄弟。

不幸的是,我在这里唯一想做的事情与您的想法非常相似。

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

<UserControl ...
             common:LifecycleManagement.CloseHandler="{Binding CloseAction}">
...
</UserControl>

然后我们的 ViewModel 上面只有一个 Action 类型的方法:
public MyVM : ViewModel
{
     public Action CloseAction
     {
          get { return CloseActionInternal; }
     }

     private void CloseActionInternal()
     {
          //TODO: stop timers, cleanup, etc;
     }
}

当我的 close 方法触发时(我们有几种方法可以做到这一点......它是一个 TabControl UI,在选项卡标题上带有“X”,诸如此类),我只是检查这个 View 是否已经向 AttachedProperty 注册了自己.如果是这样,我调用那里引用的方法。

这是一种非常迂回的方法,可以简单地检查 View 的 DataContext 是否为 IDisposable,但当时感觉更好。检查 DataContext 的问题是您可能有也需要此控件的 subview 模型。您要么必须确保您的 View 模型链转发此 dispose 调用,要么检查图表中的所有 View 并查看它们的数据上下文是否是 IDisposable(呃)。

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

然而,我做过的最好的事情是确保并使用良好的内存泄漏工具,如 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)。

关于wpf - 在 WPF PRISM/MVVM 应用程序中避免内存泄漏的最佳方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1859345/

相关文章:

wpf - 绑定(bind)到 CompositeCollection 时,ComboBox 未选择正确的项目

c# - 以异步方式以编程方式将 UIElement 添加到 View

c# - 转换器没有被调用

mvvm - Kendo MVVM Grid - 如何响应行点击事件?

内存中的 C++ 程序大小

c# - 实现可脱机工作的桌面 .NET 应用程序。

c# - XDocument.Save() 时出现内存异常

c# - 按照 MVVM 设计模式从 ViewModel 访问 this.content

java - 更改 Activity 时 Android 应用程序内存不足错误

delphi - 为什么不调用 Destroy?