.net内存泄露总结

 

l  内存泄露根源:

n  .net垃圾回收器(GC)是通过判断某个对象是否存在对于此对象的强引用,如果存在强引用则不会被回收

n  举例:

object objA = new object();

object objB = objA;

objA = null;

// 强迫回收。

GC.Collect();

objB.ToString();

n  objA引用的对象并没有被回收,因为这个对象还有另一个引用,ObjB

n  解决方法:

u  断开对象的强引用

u  使用弱引用替代强引用

参考文献:

         http://blog.csdn.net/sykpboy/archive/2005/04/11/342971.aspx

http://www.cnblogs.com/bayonetxxx/archive/2009/06/02/1494728.html

 

l  泄露实例:

1.       时间句柄使用

a)         Code

Window1.w1.TextBox1.TextChanged += new TextChangedEventHandler(TextBox1_TextChanged);

b)         Fix:

Window1.w1.TextBox1.TextChanged -= new TextChangedEventHandler(TextBox1_TextChanged);

c)         Ps:windows1存在对当前窗口的强引用,使得在windows1生命周期内当前窗口无法回收。

2.       数据绑定使用

a)         Code

myDataBinding = new Binding("Children.Count");

myDataBinding.Source = myGrid;

myDataBinding.Mode = BindingMode.OneWay;

MyTextBlock.SetBinding(TextBlock.TextProperty, myDataBinding);

或是

<TextBlock Name="MyTextBlock" Text="{Binding ElementName=myGrid, Path=Children.Count}" />

 

b)         Fix:

BindingOperations.ClearBinding(MyTextBlock, TextBlock.TextProperty);

c)         Ps:这种内存泄露只发生在Path属性不是一个依赖属性并且不是一个继承自InotifyPropertyChanged的类并且还要有一个强引用存在。

d)         微软描述:http://support.microsoft.com/kb/938416/en-us/

3.       命令绑定使用

a)         Code

command = new RoutedCommand("ClearBox", this.GetType());

command.InputGestures.Add(new KeyGesture(Key.F5));

myCmdBinding = new CommandBinding(command, F5CommandExecute);

Window1.w1.CommandBindings.Add(myCmdBinding); //add binding to Window 1

 

b)         Fix:

Window1.w1.CommandBindings.Remove(myCmdBinding);

c)         Ps:命令绑定是一种强引用。使得windows1中的对象在windows1回收前无法被回收。

 

4.       静态事件句柄使用

a)         Code

Application.Current.Activated += new EventHandler(App_Activated);

b)         Fix:

Application.Current.Activated -= new EventHandler(App_Activated);

c)         Ps:当前窗口存在一个关于静态事件的引用所以不能被释放

 

5.       BitmapImage被设置为Image Source

a)         Code

static BitmapImage bi1;

bi1 = new BitmapImage(new Uri("Bitmap1.bmp",UriKind.RelativeOrAbsolute));    //bi1 is static

//bi1.Freeze() //if you do not Freeze, your app will leak memory

m_Image1 = new Image();

m_Image1.Source = bi1; 

MyStackPanel.Children.Add(m_Image1);

 

b)         Fix:

bi1.Freeze();

c)         Ps:WPF保持一个强引用在静态BitmapImageImage之间。

6.       BitmapImage被设置为Image Source(多引用)

a)         Code

 static BitmapImage bi1 =

   new BitmapImage(new Uri("Bitmap1.bmp", UriKind.RelativeOrAbsolute));

static BitmapImage bi2 =

   new BitmapImage(new Uri("Bitmap2.bmp", UriKind.RelativeOrAbsolute));

if (bi2.CanFreeze)   

      bi2.Freeze();

//bi1.Freeze() //even though you are really using bi2 for Image Source, you also need to Freeze bi1 it to avoid leak  

m_Image1 = new Image();

m_Image1.Source = bi1;      // use un-frozen bitmap, which causes the leak

m_Image1.Source = bi2;      // use frozen bitmap

MyStackPanel.Children.Add(m_Image1);

 

b)         Fix:

bi1.Freeze();

c)         Ps:Image获得一个新的source (e.g. m_Image1.Source = bi2;),WPF不会去移出老被勾住的bi1对象。

7.       下载BitmapImageImage Source

a)         Code

BitmapImage image = new BitmapImage();

image.BeginInit();

image.UriSource = new Uri(@http://www.somesite.com/some_image.png,

                          UriKind.RelativeOrAbsolute);

image.CacheOption = BitmapCacheOption.OnLoad;

image.CreateOptions = BitmapCreateOptions.None;

image.EndInit();

 

m_Image1 = new Image();

m_Image1.Source = image;  

MyStackPanel.Children.Add(m_Image1);

 

b)         Fix: 将所需下载的BitmapImage先下载到一个临时文件夹中然后在使用本地的BitmapImage

c)         Ps:WPF不会移出一个被用于网络下载的特定对象的内部引用。这种内存泄露只发生于从Internet上下载图片。

8.       初始HWNDXP上被撤销就会导致CMilChannel泄漏

a)         Fix: 在创建任何其他的HWND之前先创建一个新的HwndSource。这样WPF将使用这个HwndSource去发送从渲染线程到UI线程的消息。这就保证所有的消息被处理。

b)         Ps:这种内存泄露的发生是因为WPF使用HWND去发送从渲染线程到UI线程的消息。当销毁第一个HWND并且在新窗口中开始一个动画,这就会引起从渲染线程到UI线程的消息堆积而没有被处理,泄露内存。

9.       使用绑定的每条线程会导致ShutdownListener泄漏

a)         Fix: 无法解决

b)         Ps:这种内存泄露的发生是因为在每个使用了绑定的线程中,使用了WPF的数据绑定的事件句柄被挂钩了但从不会被解挂钩。例如建立很多新的线程并且每个线程都创建一个使用数据绑定的新窗口。

10.   使用绑定的每条线程会导致ShutdownListener泄漏

a)         Fix: 无法解决

b)         Ps:这种内存泄露的发生是因为在每个使用了绑定的线程中,使用了WPF的数据绑定的事件句柄被挂钩了但从不会被解挂钩。例如建立很多新的线程并且每个线程都创建一个使用数据绑定的新窗口。

11.   XP的硬件渲染过程中创建和销毁WriteableBitmap 

a)         Fix: 设置HwndTarget.RenderMode = RenderMode.SoftwareOnly强制使用软件渲染

12.   Viewport3D w/ VisualBrush, WriteableBitmap, etc, leaks in Windows XP in SW 

a)         Fix:

                         i.              如果可以,使用硬件渲染的方法。

                        ii.              如果硬件渲染不行,使用SolidColorBrush来替换。

b)         Ps:VisualBrush, WriteableBitmap或是一些可选的其他类在Viewport3D中使用并且处于软件渲染的模式下。

参考文献:http://blogs.msdn.com/jgoldb/archive/2008/02/04/finding-memory-leaks-in-wpf-based-applications.aspx

l  .net GC工作原理:

http://www.cnblogs.com/RicCC/archive/2009/09/01/dotnet-memory-management-and-garbage-collection.html

http://www.qqread.com/data-structure/u454338.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值