1.GC只能回收堆里的托管资源
2.GC 回收,"代"的概念
.net 托管资源分三代,代数越大 资源的生命周期越长.
0 代 和1代的资源比较少可以比较频率的回收, 回收2代以上差不多等于对整个应用程序的堆进行遍历了,比较不适合频繁的回收.
GC.Collection() 对所有代的资源进行遍历 回收, GC.collection(1) 则是只回收0代和1代
3.GC回收的过程
对没有被引用的堆资源标记成可回收,对已标记成可回收的资源进行回收,
对于有析构函数的资源判断是否已执行过析构函数,如果没有执行过,对其进行复活.如果有执行过了,标记成可回收,下次GC才回收.
回收完后堆中的资源压缩空间,可以理解成 垃圾箱中的一部份垃圾被灭霸消灭了,把垃圾箱重新踩实,堆中的地址发生了变化,栈,静态引用,CPU寄存器引用的指针更新地址
4.Finalization
在GC回收的过程中讲到析构函数,所以有必要补充的说一下什么是析构函数
publci class MyClass { ~MyClass() { //在下就是析构函数 } }
析构函数的作用是用来释放非托管资源.C++资源 , stream ,ect..但是它只能被GC调用,回收的时机是不确定的.
5 IDispseable 接口
如果只是实现了析构函数,那么回收的时间不能确定,性能相对来说比较差.所以.Net给出另一个答案,IDispseable接口
此接口中只有一个方法 void Dispose();
void Dispose() { //释放非托管资源
GC.SuppressFinalize(this); //GC在回收时将不再调用此类的析构函数 }
用这个方法释放非托管之后还要执行这行代码 .
Dispose和Finalizeter 可以一起使用.MSDN上推荐的实现如下
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace MemoryTest.Model 9 { 10 public class MyClass : IDisposable 11 { 12 #region 变量声明 13 // 指向外部非托管资源 14 private IntPtr handle; 15 // 此类使用的其它托管资源. 16 private Component Components; 17 // 跟踪是否调用.Dispose方法,标识位,控制垃圾收集器的行为 18 private bool isDisposed = false; 19 #endregion 20 21 #region Finalizer 22 ~MyClass() 23 { 24 Dispose(false); 25 } 26 #endregion 27 28 #region IDispseable 接口实现 29 public void Dispose() 30 { 31 Dispose(true); 32 GC.SuppressFinalize(this); 33 } 34 #endregion 35 36 #region 释放方法 37 /// <summary> 38 /// 释放非托管资源 39 /// </summary> 40 /// <param name="isManual">手动调用为true,系统调用为flase</param> 41 protected virtual void Dispose(bool isManual) 42 { 43 if (isDisposed) return; 44 isDisposed = true; 45 //释放非托管资源 46 handle = IntPtr.Zero; 47 48 if (isManual) 49 { 50 //释放其他disose对象 51 Components?.Dispose(); 52 } 53 54 } 55 #endregion 56 } 57 }