先看下面的代码:
private void button1_Click(object sender, System.EventArgs e)
{
TestObj obj = new TestObj();
obj.WriteSomethin( "text" );
GC.Collect();
GC.WaitForPendingFinalizers();
doStuff();
}
private void doStuff()
{
for ( int n = 1; n <= 5; n++ )
{
System.Threading.Thread.Sleep( 1000 ); //simulate long running operation
System.IO.StreamWriter sw = new System.IO.StreamWriter( @"C:\Test.log", true );//append to file
sw.WriteLine( "Iteration " + n );
sw.Close();
}
}
}
public class TestObj : IDisposable
{
~TestObj()
{
AllDone();
}
public void Dispose()
{
AllDone();
}
private void AllDone()
{
System.IO.StreamWriter sw = new System.IO.StreamWriter( @"C:\Test.log", true );//append to file
sw.WriteLine( "TestObj Destroyed " + System.DateTime.Now.ToShortTimeString() );
sw.Close();
}
public void WriteSomethin( string strStuff )
{
System.IO.StreamWriter sw = new System.IO.StreamWriter( @"C:\Test.log", true );//append to file
sw.WriteLine( strStuff );
sw.Close();
}
}
你运行上面的代码,然后点击button1,不关闭程序,直接查看C:\Test.log,你会看到下面的内容:
text
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Iteration 5
看来程序没有调用析构函数,因为程序中没有出现"TestObj Destroyed"。接着关闭程序,再看一下C:\Test.log,你发现"TestObj Destroyed..."。
实现上我们是用下面的语句触发析构函数的调用的:
GC.Collect();
GC.WaitForPendingFinalizers();
究竟谁来清空“处理完成器(finalizers)队列”并触发GC去清除对象?上面的语句并没有触发对TestObj的析构函数的调用。关键的是我们不能准确控制对象将在什么时候被运行时收集。
现在,我们增加第二个按钮并添加下面的代码:
private void button2_Click( object sender, System.EventArgs e )
{
using( TestObj obj = new TestObj() )
{
obj.WriteSomethin( "text" );
}
doStuff();
}
重新运行程序,点击''button2",C:\Test.log出现下面的内容:
text
TestObj Destroyed 15:45
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Iteration 5
再关闭程序,C:\Test.log中的内容为:
text
TestObj Destroyed 15:45
Iteration 1
Iteration 2
Iteration 3
Iteration 4
Iteration 5
TestObj Destroyed 15:45
我们发觉出现了两处"TestObj Destroyed".这是由于我们在 ~TestObj()与Dispose()中都调用了 AllDone()。第一个"TestObj Destroyed"是由Dispose()产生的,第二是由~TestObj()产生的。在using语句结束时,对TestObj进行了清理(但我们并没有调用GC.Collect 与 GC.WaitForPendingFinalizers),调用了Dispose(),但没有调用析构函数~TestObj(),想不明白,请高手指点。
所以,在编程中尽量避免使用GC.Collect 与 GC.WaitForPendingFinalizers,让CLR自己去管理 。
原文来自http://dotnetjunkies.com/WebLog/grant.killian/posts/6033.aspx