【发布时间】:2013-02-24 06:25:09
【问题描述】:
我使用 WPF、.Net 4、Prism 4.1 和 Unity 构建了一个 Prism 应用程序。我正在使用 DirectoryModuleCatalog 在运行时查找模块。我的视图显示在 TabControl (MainRegion) 中。当我从该区域中删除视图时,视图和视图模型仍保留在内存中并且永远不会被垃圾收集 - tabitem 被删除。经过几个小时的搜索,我无法弄清楚我做错了什么。
这是我的引导程序:
public class Bootstrapper : UnityBootstrapper
{
protected override void InitializeShell()
{
base.InitializeShell();
App.Current.MainWindow = (Window)Shell;
App.Current.MainWindow.Show();
}
protected override DependencyObject CreateShell()
{
var shell = new Shell();
return shell;
}
protected override IModuleCatalog CreateModuleCatalog()
{
return new DirectoryModuleCatalog() { ModulePath = @".\Modules" };
}
}
这是我的模块:
[Module(ModuleName = "ModuleA")]
public class Module : IModule
{
private IRegionManager _regionManager;
public Module(IRegionManager regionManager)
{
_regionManager = regionManager;
}
public void Initialize()
{
var view = new UserControl1();
//_regionManager.RegisterViewWithRegion("MainRegion", typeof(UserControl1));
_regionManager.Regions["MainRegion"].Add(view, "ModuleA");
_regionManager.Regions["MainRegion"].Activate(view);
}
}
这是添加到该区域的我的视图的视图模型:
public class ViewModel
{
public DelegateCommand RemoveView { get; set; }
public ViewModel()
{
RemoveView = new DelegateCommand(() =>
{
var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
var view = regionManager.Regions["MainRegion"].GetView("ModuleA");
regionManager.Regions["MainRegion"].Deactivate(view);
regionManager.Regions["MainRegion"].Remove(view);
});
}
}
这是视图背后的代码:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
}
我读到这可能是因为我正在实例化模块中的视图,或者可能是视图中的视图模型?当我使用 Red Gate Memory Profiler 并通过 DelegateCommand 删除视图时,视图和视图模型都被标记为无法进行垃圾收集。我没有正确切割的参考在哪里?
这是来自 Ants 的保留图:https://docs.google.com/file/d/0B4XjO9pUQxBXbGFHS1luNUtyOTg/edit?usp=sharing
这是一个 test solution 显示问题。
另外,我也在CodePlex 上发布了这个问题。
【问题讨论】:
-
嗨,克里斯。我看了你的项目。看起来您的 ViewModel 实现了 IDisposable。我发现如果不调用 Dispose(),这会对生命周期产生一些奇怪的影响(WPF 与 WinForms 不同,并没有大量使用 IDisposable)。 IDisposable 适用于关闭非托管资源(如数据库连接等),但有更好的方法。试着把它拿出来看看会发生什么。
-
我应该提到的另一件事是,您应该确保自己是对象生命周期的良好衡量标准。收集不是很确定,我在 WPF 应用程序中发现有时可能需要一段时间才能收集到一个对象。您在 ANT 中的图表看起来不错 - 引用您的视图模型的东西看起来都在某处有 WeakReference 中断,因此它们不应该固定对象。
-
绑定引用是一个强大的引用,但这应该不是问题,因为您的视图将被收集,然后收集您的 ViewModel。你检查过你的视图的生命周期吗?
UserControl1和ViewModel的生命周期应该相同。 -
@Anderson - 感谢您对此进行调查。除了我在下面列出的解决方案之外,我们还需要对未实现 INotifyPropertyChanged 的对象的绑定进行一些清理。
标签: wpf memory memory-leaks prism