c#中的GC

感谢baihaixiao 的这篇博文。

还有xmsheji的这篇。

还有这篇。

在写c#处理数据很多,处理完每次都占用很大内存,释放不掉,很是不爽。

搞明白一点c#的垃圾回收,把测试代码备份一下

//代码来源浅谈C#的垃圾回收-关于GC、析构函数、Dispose、and Finalize 
//http://blog.csdn.net/baihaixiao/article/details/4583910
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Data.SqlClient;
namespace ConsoleApplication3
{
        class Log
    {
        public static readonly string logFilePath = @"d:/log.txt";

        public static void Write(string s)
        {
            Thread.Sleep(10);
            using (StreamWriter sw = File.AppendText(logFilePath))
            //此处有可能抛出文件正在使用的异常,但不影响测试
            {
                sw.WriteLine("{0}\tTotalMilliseconds:{1}\tTotalMemory:{2}", s, 
                    DateTime.Now.TimeOfDay.TotalMilliseconds, GC.GetTotalMemory(false));
                sw.Close();
            }
        }
    }

    class World
    {
        protected FileStream fs = null;
        protected SqlConnection conn = null;

        public World()
        {
            fs = new FileStream(Log.logFilePath, FileMode.Open);
            conn = new SqlConnection();
        }

        protected void Finalize()
        {
            fs.Dispose();
            conn.Dispose();
            Log.Write("World's destructor is called");
        }
    }

    class China : World
    {
        public China()
            : base()
        {

        }

        ~China()
        //protected  void Finalize()
        //若改为Finalize则覆盖了父类的Finalize导致无法调用父类的Finalize
        {
            Log.Write("China's destructor is called");
        }

    }

    class Beijing : China
    {
        public Beijing()
            : base()
        {

        }

        ~Beijing()
        {
            Log.Write("Beijing's destructor is called");
        }
    }
    class Program
    {

        static void Main(string[] args)
        {
            // new Beijing();
            //GC.Collect();
            //GC.WaitForPendingFinalizers();
            //Log.Write("In TestOne../t/t");
            TestOne();
            Log.Write("In Main..\t\t");
        }
        static void TestOne()
        {
            //new Beijing();
            //GC.Collect();
            //GC.WaitForPendingFinalizers();
            //Log.Write("In TestOne..\t\t");

            new Beijing();
            GC.Collect();
            Log.Write("In TestOne..\t\t");

            //以下这句异常通不过,log文件没有输出,不像博主说的那样
            //Beijing bj = new Beijing();
            //GC.Collect();
            //Log.Write("In TestOne..\t\t");
        }
    }
}
/*
 * 在C#中,如果一个自定义类没有构造器,编译器会添加一个隐藏的无参构造器。但是析构函数不会自动创建。
 * 一旦析构函数创建了,终结器也便自动产生了。构构函数其实等同于如下代码:
try{
    Finalize();
}finally{
    base.Finalize();
}
 * 如果在派生类中不存在析造函数,却重载了基类的终结器,如下:
protected override void Finalize(){...}
    垃圾回收时,GC找不到析构函数,会直接调用终结器。因终结器已重写,如果在该终结器中不调用基类的终结器,
 * 那么GC将忽略基类。可以利用这个特性写一个不受垃圾回收器管辖的类,以实现某种特殊的效果。
 
 输出结果:
 
             new Beijing();
            GC.Collect();
            GC.WaitForPendingFinalizers();
            Log.Write("In TestOne..\t\t");
            
            new Beijing();
            GC.Collect();
            Log.Write("In TestOne..\t\t");

//TestOne中有GC.WaitForPendingFinalizers();
Beijing's destructor is called	TotalMilliseconds:31906036.8852	TotalMemory:374872
China's destructor is called	TotalMilliseconds:31906050.886	TotalMemory:391256
World's destructor is called	TotalMilliseconds:31906061.8867	TotalMemory:415832
In TestOne..			TotalMilliseconds:31906076.8875	TotalMemory:440408
In Main..			TotalMilliseconds:31906087.8882	TotalMemory:456792
//TestOne中无GC.WaitForPendingFinalizers();
Beijing's destructor is called	TotalMilliseconds:32140815.498	TotalMemory:391256
In TestOne..			TotalMilliseconds:32140816.4981	TotalMemory:407640
China's destructor is called	TotalMilliseconds:32140826.4986	TotalMemory:424024
In Main..			TotalMilliseconds:32140829.4988	TotalMemory:448600
World's destructor is called	TotalMilliseconds:32140843.4996	TotalMemory:473176
 
 * 
 * 
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        AA a;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
             a = new AA("D://a.txt");
            //a.Dispose();
            //AA b = new AA();
            //AA c = new AA();
            //AA d = new AA();
            // a = null;
            //GC.Collect();
            //GC.WaitForPendingFinalizers();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            a = null;
            //GC.Collect();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (a != null)
            { a.Dispose(); }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            GC.Collect();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            //立即释放a
            a = null;
            GC.Collect();
            
        }

        private void button6_Click(object sender, EventArgs e)
        {
            if (a != null)
            {
                //清空数组,等待下一次GC.Collect()时释放
                a.ClearAry();
            }
        }
    }

    /// 
    /// 参照msdn改写
    /// http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(SYSTEM.IDISPOSABLE);k(TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV3.5%22);k(DevLang-CSHARP)&rd=true
    /// 
    public class AA:IDisposable 
    {
        private bool disposed = false;
        private FileStream fs;
        private byte[] btary;
        public AA(string filepath)
        {
            btary = new byte[10000000];
            //数组全部置零
            Array.Clear(btary, 0, btary.Length);
            fs = new FileStream(filepath,FileMode.Open);
        }
        public void ClearAry()
        {
            btary = null;
            //GC.Collect();
        }
        public void Dispose()
        {
            Dispose(true);

            // This object will be cleaned up by the Dispose method. 
            // Therefore, you should call GC.SupressFinalize to 
            // take this object off the finalization queue 
            // and prevent finalization code for this object 
            // from executing a second time.
            //若程序中显示调用该类对象的Dispose()
            //执行完下句,则不会再调用析构
            GC.SuppressFinalize(this);
        }
        private void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                  //在此处填充代码,调用托管资源的Dispose
                }
                //在此处填充代码,释放非托管资源
                fs.Dispose();
                disposed = true;
            }
        }
        ~AA()
        {
            Dispose(false);
            //MessageBox.Show("析构了~");
        }
    }
}
using System;
using System.ComponentModel;

// The following example demonstrates how to create 
// a resource class that implements the IDisposable interface 
// and the IDisposable.Dispose method. 

public class DisposeExample
{
    // A base class that implements IDisposable. 
    // By implementing IDisposable, you are announcing that 
    // instances of this type allocate scarce resources. 
    public class MyResource: IDisposable
    {
        // Pointer to an external unmanaged resource. 
        private IntPtr handle;
        // Other managed resource this class uses. 
        private Component component = new Component();
        // Track whether Dispose has been called. 
        private bool disposed = false;

        // The class constructor. 
        public MyResource(IntPtr handle)
        {
            this.handle = handle;
        }

        // Implement IDisposable. 
        // Do not make this method virtual. 
        // A derived class should not be able to override this method. 
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method. 
            // Therefore, you should call GC.SupressFinalize to 
            // take this object off the finalization queue 
            // and prevent finalization code for this object 
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios. 
        // If disposing equals true, the method has been called directly 
        // or indirectly by a user's code. Managed and unmanaged resources 
        // can be disposed. 
        // If disposing equals false, the method has been called by the 
        // runtime from inside the finalizer and you should not reference 
        // other objects. Only unmanaged resources can be disposed. 
        private void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called. 
            if(!this.disposed)
            {
                // If disposing equals true, dispose all managed 
                // and unmanaged resources. 
                if(disposing)
                {
                    // Dispose managed resources.
                    component.Dispose();
                }

                // Call the appropriate methods to clean up 
                // unmanaged resources here. 
                // If disposing is false, 
                // only the following code is executed.
                CloseHandle(handle);
                handle = IntPtr.Zero;

                // Note disposing has been done.
                disposed = true;

            }
        }

        // Use interop to call the method necessary 
        // to clean up the unmanaged resource.
        [System.Runtime.InteropServices.DllImport("Kernel32")]
        private extern static Boolean CloseHandle(IntPtr handle);

        // Use C# destructor syntax for finalization code. 
        // This destructor will run only if the Dispose method 
        // does not get called. 
        // It gives your base class the opportunity to finalize. 
        // Do not provide destructors in types derived from this class.
        ~MyResource()
        {
            // Do not re-create Dispose clean-up code here. 
            // Calling Dispose(false) is optimal in terms of 
            // readability and maintainability.
            Dispose(false);
        }
    }
    public static void Main()
    {
        // Insert code here to create 
        // and use the MyResource object.
    }
}


你可能感兴趣的:(测试代码)