关于GC的使用

先看下面的代码:
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

posted @ 2004-01-25 16:10  dudu  阅读(2474)  评论(1编辑  收藏  举报