Windows Presentation Foundation即WPF,它代表着Windows平台UI的未来。微软有其自身的打算,而稍晚于WPF的Silverlight将占领Web和移动 设备市场。不过,和任何的新技术一样,都会经历一些问题,如某些相当严重的内存泄漏问题。
我们要讨论诸多内存泄漏。第一个问题已经发现一段时间,但它并没有引起大多程序员的关注,甚至是专家们的注意。引发该问题需要以下条件配合:
- 引用对象X属性P的数据绑定路径
- 对象X含直接引用或间接引用数据绑定操作的目标对象
属性P通过PropertyDescriptor对象而非DependencyProperty对象或PropertyInfo对象访问
这个问题在KB 938416中有详细的描述。
接下来是一个让人极其厌烦的Bug,它在我们使用一个数据绑定集合代替另外一个时触发。Ayende Rahien有引发该问题的源代码。Mike Brown解释道:
经过深入研究以后,我发现该绑定系统并没有解除对“Name”属性的监听程序,但相关数据已被修改。
这 很明显是一个Bug,它和绑定系统有关。当你注意到数据被修改过,而非解除已有绑定(这次假设Name绑定Textblock)并再次使用该元素,就像重 新创建元素集那样。不幸的是,Textblock从来没有解除该绑定。现在如果让数据变成可观测的集合(必要情况下把匿名类型转换为标准的类)并让该集合 触发CollectionChanged事件(例如:Da
ta[0]=Da ta[0]),一切运行正常。
以下的内存泄漏来自于jgoldb的微软博客上:
- 如果初始HWND在XP上被撤销就会导致CMilChannel泄漏
- 使用绑定的每条线程会导致ShutdownListener泄漏
- 在XP的HW中创建和消除WriteableBitmap
- SW Viewport 3D w/ VisualBrush和WB等,都会在XP上引起泄漏问题
除了这些泄漏以外,他还列出了一些其他的常见开发错误导致的内存泄漏,以及一些已修复的WPF问题。
wpf内存泄漏问题解决方案:
1、 如果用MVVM模式,View里面有图片,ViewModel里面有View引用,要把ViewModel里面的View设置为空,View里面的DataContext设置为空,不然有可能导致内存泄漏
清除引用:
this.Page.DataContext = null;
this.Page = null;
2、 类与类之间尽量不要互相引用,如果相互引用了要手动设置里面的引用为空,不然 会导致内存泄漏
Class1 class1 =new Class1();
Class2 class2 = new Class2();
class1.Class2 = class2;
class2.Class1 = class1;
清除引用:
class2.Class1 = null;
class2 = null;
class1.Class2 = null;
class1 =null;
3、 自定义控件里面有Image、BitMapSource属性值之类或者引用类属性时,要手动删除并设置为空
CustomControl cc = new CustomControl();
BitMapSource bms = new BitMapSource();
bms.UriSource = ……;
cc.Image = new Image(){Source= bms };
清除引用:
cc.Image=null;
bms =null;
4、 MVVM模式里面继承INotifyPropertyChanged的ViewModel里面的命令(用CommandManager.RegisterClassCommandBinding)有可能导致内存泄漏
protected ICommand CreateCommand(Action<ExecutedRoutedEventArgs> executed, Action<CanExecuteRoutedEventArgs> canExecute)
{
var rCommand = new RoutedCommand();
var cBinding = new CommandBinding(rCommand);
CommandManager.RegisterClassCommandBinding(typeof(UIElement), cBinding);
cBinding.CanExecute += (s, e) =>
{
if (canExecute != null)
canExecute(e);
else
e.CanExecute = true;
};
cBinding.Executed += (s, e) =>
{
executed(e);
};
return rCommand;
}
修改成:
protected ICommand CreateCommand(Action<object> execute)
{
return new RelayCommand(execute);
}
public class RelayCommand : Icommand
{
………….
}
5、 页面关闭时没结束的线程要结束线程
6、 页面关闭时静态变量要设置为空
7、 使用事件时,如果是一个类的事件在另一个类里面被注册(委托方法在这个类里面),要注销事件
Window1.w2.TextBox1.TextChanged += new TextChangedEventHandler(this.TextBox1_TextChanged);
Window1.w2.TextBox1.TextChanged -= new TextChangedEventHandler(this.TextBox1_TextChanged); 事件
8、 用静态事件时要注销事件
9、 在Image里面使用BitMapImage时要用
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.UriSource = new Uri(path);
bi.EndInit();
bi.Freeze();
10、 调用垃圾回收
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
11、 如果绑定的数据源没有实现INotifyPropertyChanged,可能导致内存泄漏
在 WPF 中,不标记为 OneTime 必须侦听属性的一个数据绑定操作从源对象 (对象 X) 更改通知。WPF 从 INotifyPropertyChanged 界面使用 DependencyProperties 类的内置通知。如果 DependencyProperties 类和 INotifyPropertyChanged 接口都不可用,WPF 使用 ValueChanged 事件。 此行为涉及到与属性 P 相对应的 PropertyDescriptor 对象上调用 PropertyDescriptor.AddValueChanged 方法。 遗憾的是,此操作会导致公共语言运行库 (CLR) 可以创建从此 PropertyDescriptor 对象 X 的强引用。 CLR 还保留全局表中的 PropertyDescriptor 对象的引用
public class CustomCollectionClass : INotifyPropertyChanged
============ 欢迎各位老板打赏~ ===========
与本文相关的文章
- · WPF仿360浏览器弹出界面
- · 微软放弃 Silverlight?
- · .NET操作IIS详解
- · WPF实战系列-图形透明度与混色特效
- · The instance of entity type ‘Customer’ cannot be tracked because another instance with the same key value for {‘Id’} is already being tracked.
- · .NET8实时更新nginx ip地址归属地
- · 解决.NET Blazor子组件不刷新问题
- · .NET8如何在普通类库中引用 Microsoft.AspNetCore
- · .NET8 Mysql SSL error
- · ASP.NET Core MVC的Razor视图渲染中文乱码的问题
- · .NETCORE 依赖注入服务生命周期
- · asp.net zero改mysql