.NET垃圾收集

本文探讨了两种处理非托管资源的方法:实现Finalize方法和继承IDisposable接口。通过这两种方式,可以确保昂贵的非托管资源得到适当管理。

垃圾回收是一个只处理托管资源的不确定事件。把object = null后等着GC回收就行了。对于托管资源,垃圾收集就能很好的工作。

问题是:有些昂贵的非托管资源如何管理?

 

解决方法一:实现Finalize方法管理对象的清理。

                         包含Finalize方法的对象不同于那些不含此方法的对象。前者通常在堆中分配内存,重要的是指向它的指针放在“最终化队列”中。垃圾收集期间,GC扫描“最终化队列”,搜索不可达对象的指针,并将其移到"不可达队列"中。该队列中引用的对象仍存活,以便某个后台线程能扫描该队列,并对每个引用的对象执行Finalize方法。再次发生垃圾收集时才释放这些内存。
                         最好是创建一个析构函数代替Finalize,并将Finalize方法中代码放入析构函数。编译器将析构函数代码转化为一个提供异常处理的Finalize方法。其中还包含对基类的Finalize方法。

 

解决方法二:继承IDisposable接口

                         很明显第一种方法依赖GC所以释放的时间还是不确定,幸运的是,CLR提供了Dispose来通知对象完成清理。
                         可以实现IDisposable接口,在Dispose函数内写清理代码。让客户调用Dispose清理资源。这时又有两个问题:
                         1.若已经对象Dispose后又调用对象方法该怎么办?
                            很明显一个bool型IsDiposed字段控制使用,若已经Dispose则抛出异常(ObjectDisposedException)
                          2.不能保证客户会调用Dispose?
                             所以最好应该也实现Finalize(构造一个析构函数),当客户没有调用Dispose时让GC回收。一般Dispose函数和析构函数调用同一个清理资源的函数。
                         3.如果实现Finalize,那么在调用了Dispose后。如何保证GC不再参与回收资源(即GC不再调用Finalize)?
                        在Dispose函数内执行GC.SuppressFinalize(this);此静态方法可以通知GC不把对象放入不可达队列。这样就不会Finalize了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值