C#中的垃圾回收

C#中的垃圾回收

简单说一下C#中的内存管理、垃圾回收和资源管理

为什么需要垃圾回收

我们每次在C#中创建一个对象(Object),CLR都会在堆中给Object分配一块内存,但是系统内存总有用完的时候,这是就需要清理一些用过的内存
CLR会判断所有创建出来的对象中,那些不会再被程序用到,然后把它们销毁。

任何进程被触发后,都会从物理内存中分配到一块虚拟空间,程序处理的也是虚拟空间而不是物理内存。GC分配和回收内存时,处理的也是虚拟空间

GC工作机制

当GC被激活时,它会找出不再使用的对象(已经死亡的对象,也就是所谓的垃圾),然后对仍然在使用的对象进行压缩并尝试释放内存。
一般情况下,堆(heap)被分为三代(Generation),并根据对象在内存中的存活时间进行存储和处理。三代堆的区别如下:
0代:存储在内存中存活时间最短的对象,如一些临时性的对象(temporary object),在此代中垃圾处理的频率最高
1代:0代和2代堆之间的一个缓存
2代:存储在内存中存活时间最长的对象,比如静态static或全局global变量。
在0代中的对象如果没有被回收,它将会被移至1代中,同样,如果对象在1代中没有被回收,它将被移至2代中。

GC运行过程

首先要说一下“根”的概念,一个根可以是:
一个正在制定的方法的局部变量或参数
一个静态变量
存储在结束队列中的一个对象

一次垃圾回收过程开始时,GC会认为堆中的所有对象都是垃圾。
GC检查所有的对象,当一个对象被根引用了,那么对这个对象进行标记。当所有的对象都被遍历后,没被标记过的对象就是垃圾对象,应该进行回收。
垃圾回收时,先释放垃圾对象所占用的内存,然后把未回收的对象移到这里来压缩堆(当然移动后对象的位置改变了,所有对象的引用也要重新修正)

托管资源(Managed Source)和非托管资源(Unmanaged Source)

所有CLR创建并管理的均为托管资源,如string、bool等类型的变量
在.net库外创建而且无法被CLR管理的均为非托管资源,比如COM对象,FileStream,Interop对象等。

回收非托管资源

当我们创建了一个非托管对象时,当我们使用完这些非托管对象(例如Filestream、database connection、network instance等),GC是无法意识到它们已经成为了垃圾。

清理非托管资源的方法是实现IDisposable借口和Dispose方法,实现Dispose方法有2个途径
使用SafeHandle类实现Dispose
重写Object.Finalize方法

通过SafeHandle类实现Dispose

 class clsDispose_safe
    {
        // Take a flag to check if object is already disposed
        bool bDisposed = false;

        // Create a object of SafeHandle class
        SafeHandle objSafeHandle = new SafeFileHandle(IntPtr.Zero, true);

        // Dispose method (public)
        public void Dispose1()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // Dispose method (protected)
        protected virtual void Dispose(bool bDispose)
        {
            if (bDisposed)
                return;

            if (bDispose)
            {
                objSafeHandle.Dispose();
                // Free any other managed objects here.
            }

            // Free any unmanaged objects here.
            //
            bDisposed = true;
        }
    }

通过重写Object.Finalize方法实现Dispose

    class clsDispose_Fin
    {
        // Flag: Has Dispose already been called?
        bool disposed = false;

        // Public implementation of Dispose pattern callable by consumers.
        public void Dispose()
        {
            Dispose1(true);
            GC.SuppressFinalize(this);
        }

        // Protected implementation of Dispose pattern.
        protected virtual void Dispose1(bool disposing)
        {
            if (disposed)
                return;

            if (disposing)
            {
                // Free any other managed objects here.
                //
            }

            // Free any unmanaged objects here.
            //
            disposed = true;
        }

        ~clsDispose_Fin()
        {
            Dispose1(false);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值