CLR via C# 读书笔记 5-3 使用GC Handle手动控制对象生命周期
使用System.Runtime.InteropServices.GCHandle类来手动控制对象的生命周期
(个人感觉这里可能有一些问题...只是草稿而已..还请高手指正)
1.GCHandle.Alloc
传递一个Object和一个GCHandleType枚举给Alloc方法以控制Object的生命周期,返回一个GCHandle
1) GCHandleType.Weak 此标志位允许你监视对象生命周期,当对象被标记为不可到达的时候,这个对象的Finalize方法可能执行也可能没有执行,这个对象可能依然存在于内存中
2) GCHandleType.WeakTrackResurrection 此标志位允许你监视对象生命周期,对象的Finalize方法肯定会被执行(如果有的话),内存会被回收
3) GCHandleType.Nomal 此标志位允许你控制对象生命周期,保证对象一直存在,在GC的时候该对象可能被移动位置
4) GCHandleType.Pinned 此标志位允许你控制对象生命周期,保证对象一直存在,在GC的时候该对象不会被移动
2.GC和GCHandle的关系
GCHanlde 是一个轻量级的值类型,内部只包含一个实例Field:IntPtr
1) GC标记所有可到达的对象,然后GC扫描 GC Handle 表, 所有标记为Normal和Pinned的对象将被视为可到达的对象(包括这些对象的成员 这是一个递归的过程)
2) GC扫描GC Handle表中所有标记为Weak的实体,如果该实体所指向的Object被标记为不可到达的,(也就是标记为垃圾),那么这个拥有指针的实体将置为null
3) GC扫描终结列表(Finalization List 不知道怎么翻译...),将所有指向不可到到达的指针移动到Freachable Queue,然后被指向的对象标记为可到达的
4) GC扫描GC Handle 表中所有标记为WeakTrackResurrection 的实体,如果该实体所指向的Object被标记为不可到达的,那么拥有这个指针的实体将置为null
5) GC Compact内存(当然有的时候GC不并执行这个动作,因为它觉得不值得),此外Pinned的对象不会被移动
3.应用
1) c# fixed关键字 就是GCHandleType.Pinned 的实际应用之一
2) Weak标记可以让你知道什么时候一个对象已经决定被回收,(但是这个对象也许还没有被回收)
3) WeakTrackResurrection标记可以让你知道什么时候一个对象的内存被回收(按书中所说...这个东西好像没啥用)
4) WeakReference其实就是对GCHandle的封装