从 ContentControl 中使用的 Ioc 的 viewModel 中释放内存
Free memory from viewModel from Ioc used in ContentControl
我目前正在使用 ContentControl 通过设置 VM 和使用默认数据模板来显示我的视图:
<UserControl.Resources>
<DataTemplate DataType="{x:Type vm:MyViewViewModel}">
<views:MyView />
</DataTemplate>
</UserControl.Resources>
<ContentControl Content="{Binding ContainerContent}"/>
这是我的 ContainerContent:
public ViewModelBase ContainerContent
{
get
{
return _containerContent;
}
set
{
if (_containerContent != null)
_containerContent.Cleanup();
_containerContent = value;
RaisePropertyChanged("ContainerContent");
}
}
我目前使用 SimpleIoc 通过 serviceLocator 加载 ViewModel:
ContainerContent = ServiceLocator.Current.GetInstance<MyViewViewModel>();
效果很好,可以正确显示我的视图,并将 viewModel 分配给内容。
不幸的是,当我想从我的 ContentControl 中删除视图(和视图模型)时,我的内存仍在使用,因为 ViewModel、View 和 SimpleIoc.The 视图之间的释放顺序引用了它时间(我认为这个时间是由于容器上RaisePropertyCHange之后的绑定)
我目前使用一种方法来删除内容:
public void QuitCurrentContainerViewModel<T>() where T : class
{
ContainerContent = null;
Task.Factory.StartNew(() =>
{
if (/*!*/SimpleIoc.Default.ContainsCreated<T>())
{
SimpleIoc.Default.Unregister<T>();
}
DispatcherHelper.RunAsync(() =>
{
MessageBox.Show("Do GC now");
GC.Collect();
}, DispatcherPriority.ApplicationIdle);
});
}
(使用dispatcher和priority是测试)
如果我调用它,有时我的内存会被正确释放,但并非总是如此。
在任何情况下,如果我从快捷方式强制执行 GC.Collect,我的内存就会得到正确管理。
在我的情况下释放内存的好方法是什么?
谢谢!
编辑:我的错,它与该代码一起工作正常(在我的 QuitCurrentContainerViewModel 方法中我使用了这个检查:
if (!SimpleIoc.Default.ContainsCreated<T>())
但我需要这个:
if (SimpleIoc.Default.ContainsCreated<T>())
这种方式好像没问题。
What is the good way to release the memory in my case ?
为每个对象使用 IDisposable 模式,并在通用类型说明符中要求它。这样就可以直接调用顶级实体,随后可以清除所有遵循接口的子引用。
请记住,有订阅的实例,尽管在代码中没有直接引用该实例,但如果它们有任何活动的订阅,它们将成为 固定 并保持活动状态;让垃圾收集器远离。
在对实例进行垃圾回收之前,必须取消链接所有订阅。
If I call this sometimes my memory is correctly freed, but not always.
您是否正在查看应用程序的私有字节?对于 OS 报告一个完整的总数,如果 OS 没有被强调,它不会带走内存足迹允许应用程序呼吸可以这么说。专用字节将在完整分配的总数中上下波动。
所以您可能监控了错误的值。
这是我的代码,没有无用的调用
public ViewModelBase ContainerContent
{
get
{
return _containerContent;
}
set
{
if (_containerContent != null)
_containerContent.Cleanup();
_containerContent = value;
RaisePropertyChanged("ContainerContent");
}
}
public void QuitCurrentContainerViewModel<T>() where T : class
{
ContainerContent = null;
Task.Factory.StartNew(() =>
{
if (SimpleIoc.Default.ContainsCreated<T>())
{
SimpleIoc.Default.Unregister<T>();
GC.Collect();
}
//TODO: Do navigation or change of content
});
}
这是我加载的 ContentContainer
Task.Factory.StartNew(() =>
{
if (!SimpleIoc.Default.ContainsCreated<MyViewModel>())
SimpleIoc.Default.Register<MyViewModel>();
ContainerViewModel.ContainerContent = SimpleIoc.Default.GetInstance<MyViewModel>();
});
如果有人有更好的方法来解决这个内存管理,我完全开放。
我目前正在使用 ContentControl 通过设置 VM 和使用默认数据模板来显示我的视图:
<UserControl.Resources>
<DataTemplate DataType="{x:Type vm:MyViewViewModel}">
<views:MyView />
</DataTemplate>
</UserControl.Resources>
<ContentControl Content="{Binding ContainerContent}"/>
这是我的 ContainerContent:
public ViewModelBase ContainerContent
{
get
{
return _containerContent;
}
set
{
if (_containerContent != null)
_containerContent.Cleanup();
_containerContent = value;
RaisePropertyChanged("ContainerContent");
}
}
我目前使用 SimpleIoc 通过 serviceLocator 加载 ViewModel:
ContainerContent = ServiceLocator.Current.GetInstance<MyViewViewModel>();
效果很好,可以正确显示我的视图,并将 viewModel 分配给内容。
不幸的是,当我想从我的 ContentControl 中删除视图(和视图模型)时,我的内存仍在使用,因为 ViewModel、View 和 SimpleIoc.The 视图之间的释放顺序引用了它时间(我认为这个时间是由于容器上RaisePropertyCHange之后的绑定)
我目前使用一种方法来删除内容:
public void QuitCurrentContainerViewModel<T>() where T : class
{
ContainerContent = null;
Task.Factory.StartNew(() =>
{
if (/*!*/SimpleIoc.Default.ContainsCreated<T>())
{
SimpleIoc.Default.Unregister<T>();
}
DispatcherHelper.RunAsync(() =>
{
MessageBox.Show("Do GC now");
GC.Collect();
}, DispatcherPriority.ApplicationIdle);
});
}
(使用dispatcher和priority是测试)
如果我调用它,有时我的内存会被正确释放,但并非总是如此。
在任何情况下,如果我从快捷方式强制执行 GC.Collect,我的内存就会得到正确管理。
在我的情况下释放内存的好方法是什么?
谢谢!
编辑:我的错,它与该代码一起工作正常(在我的 QuitCurrentContainerViewModel 方法中我使用了这个检查:
if (!SimpleIoc.Default.ContainsCreated<T>())
但我需要这个:
if (SimpleIoc.Default.ContainsCreated<T>())
这种方式好像没问题。
What is the good way to release the memory in my case ?
为每个对象使用 IDisposable 模式,并在通用类型说明符中要求它。这样就可以直接调用顶级实体,随后可以清除所有遵循接口的子引用。
请记住,有订阅的实例,尽管在代码中没有直接引用该实例,但如果它们有任何活动的订阅,它们将成为 固定 并保持活动状态;让垃圾收集器远离。
在对实例进行垃圾回收之前,必须取消链接所有订阅。
If I call this sometimes my memory is correctly freed, but not always.
您是否正在查看应用程序的私有字节?对于 OS 报告一个完整的总数,如果 OS 没有被强调,它不会带走内存足迹允许应用程序呼吸可以这么说。专用字节将在完整分配的总数中上下波动。
所以您可能监控了错误的值。
这是我的代码,没有无用的调用
public ViewModelBase ContainerContent
{
get
{
return _containerContent;
}
set
{
if (_containerContent != null)
_containerContent.Cleanup();
_containerContent = value;
RaisePropertyChanged("ContainerContent");
}
}
public void QuitCurrentContainerViewModel<T>() where T : class
{
ContainerContent = null;
Task.Factory.StartNew(() =>
{
if (SimpleIoc.Default.ContainsCreated<T>())
{
SimpleIoc.Default.Unregister<T>();
GC.Collect();
}
//TODO: Do navigation or change of content
});
}
这是我加载的 ContentContainer
Task.Factory.StartNew(() =>
{
if (!SimpleIoc.Default.ContainsCreated<MyViewModel>())
SimpleIoc.Default.Register<MyViewModel>();
ContainerViewModel.ContainerContent = SimpleIoc.Default.GetInstance<MyViewModel>();
});
如果有人有更好的方法来解决这个内存管理,我完全开放。