这期博客的话题有些沉重,我们来讨论.net对象的生生死死。首先,要给生死下个定义。在这篇博客 中,每当谈及一个对象是死了的对象,指的是用户无法再获得其引用。这个定义是个对用户友好的定义 ,因为有很多时候,对象还残存在托管堆上,CLR依旧可以通过一些手法来获得它(比如RCW缓存中通过 SyncBlk),但是这种“生不如死”的状态不在今天的讨论范围之内。
言归正传。众所周知,.NET倚仗GC管理分配在托管堆上的对象(也就是new出来的东东)。为了提供类 似c++中析构函数的功能,也就是在对象即将死去的时候,执行一段用户代码来做一些清理工作,比如在 一个COM组件上调用它的Release方法。
出于性能的考虑,CLR使用一个独立的线程来执行对象的Finalize方法,所以Finalize方法的执行并 不是GC.Collect的一部分。下面一个程序验证了这个说法。
using System;
using System.Threading;
class ObjectWithFinalizer
{
~ObjectWithFinalizer()
{
Thread.Sleep(1000);
Console.WriteLine("Finalize in thread {0}", Thread.CurrentThread.ManagedThreadId);
}
}
class Program
{
public static void Main()
{
Console.WriteLine("Run in thread {0}", Thread.CurrentThread.ManagedThreadId);
ObjectWithFinalizer owf = new ObjectWithFinalizer();
GC.Collect();
Console.WriteLine("GC.Collect() end");
}
}
程序的运行结果是
Run in thread 1
GC.Collect() end
Finalize in thread 2