【C#语法】C#中的托管资源和非托管资源


托管资源和非托管资源

托管资源,顾名思义,就是依托在.net平台,在托管堆中创建,它的释放不由人工进行干预,而是由.net的垃圾回收器GC自动进行释放。

相对于托管资源,非托管资源主要是操作系统级别的资源,.net平台无法对其释放,需要我们手动进行资源的回收。非托管资源一般对应于windows中的内核对象,常见的非托管资源如下所示:

.NET对象

引用到的Windows对象句柄

分类

System.Threading.Tasks.Task

访问令牌

内核对象

System.IO.FileSystemWatcher

更改通知

内核对象

System.IO.FileStream

文件

内核对象

System.Threading.AutoResetEvent
System.Threading.ManualResetEvent
System.Xaml.XamlBackgroundReader

事件

内核对象

System.Diagnostics.EventLog

事件日志

内核对象

System.Threading.Thread

线程

内核对象

System.Threading.Mutex

互斥量

内核对象

System.Threading.Semaphore

信号量

内核对象

System.Windows.Forms.Cursor

光标

用户对象

System.Drawing.Icon

图标

用户对象

System.Windows.Forms.Menu

菜单

用户对象

System.Windows.Forms.Control

窗口

用户对象

System.Windows.Forms.Control
System.Drawing.BufferedGraphicsManager
System.Drawing.Bitmap

位图

GDI对象

System.Drawing.SolidBrush
System.Drawing.TextureBrush

画刷

GDI对象

System.Drawing.Font

字体

GDI对象

 

 

二、非托管资源的回收

垃圾回收器GC在回收非托管资源时,会调用Object.Finalize()方法,该方法默认情况下是空,且不能进行重载。它是由编译器自动生成的,编译器会根据析构函数里,对非托管资源的回收,自动生成Object.Finalize()方法对非托管资源进行回收。

另外一种非托管资源回收的方法是,我们自定义的类继承IDispose接口,该接口提供了一个Dispose()方法。在这个方法中可以对非托管资源进行释放。原则上任何包含非托管资源的类,必须继承该接口。

使用继承IDispose的类时,需要使用using关键字进行配合。比如我们自定义了一个类MyClass,继承了IDispose接口,那么我们可以使用using关键字对其进行如下操作:

 using(MyClass mc=new MyClass())
            {
 
            }

当整个语句块结束之后,系统会自动调用MyClassDispose()方法,以释放非托管资源。

资源安全类

  在一个包含非托管资源的类中,关于资源释放的标准做法是:

  (1)继承IDisposable接口;

  (2)实现Dispose()方法,在其中释放托管资源和非托管资源,并将对象本身从垃圾回收器中移除(垃圾回收器不在回收此资源);

  (3)实现类析构函数,在其中释放非托管资源。

我们把符合上述三点条件的类叫做资源安全类,按照上述原则我们可以自己定义一个资源安全类:

  class MyClass:IDisposable
    {
 
        /// <summary>
        /// 非托管资源
        /// </summary>
        private FileStream file;
 
        /// <summary>
        /// 标志是否被释放的布尔量
        /// </summary>
        private bool Disposed = false;
 
        /// <summary>
        /// 继承自IDispose的Dispose方法,保证在使用using关键字时能够及时释放资源.
        /// 注意using语句块结束后是不会调用析构函数的。
        /// </summary>
        public void Dispose()
        {
            if (Disposed == false)
            {
                if (file != null)
                {
                    file.Close();
                }
                Disposed = true;
            }
            //将对象从垃圾回收列表中移除
            //这样在垃圾回收时只释放托管资源,从而提高了效率
            GC.SuppressFinalize(this);
        }
 
        /// <summary>
        /// 析构函数中同样进行非托管资源的释放,这样在编译阶段将会生成Finalize()方法,保证系统在垃圾回收阶段调用该方法释放
        /// 非托管资源.
        /// 注意这里定义的析构函数只是为了生存Finalize的方法,实际程序的执行过程中是不会进入析构函数中的。
        /// </summary>
        ~MyClass()
        {
            if (Disposed == false)
            {
                if (file != null)
                {
                    file.Close();
                }
                Disposed = true;
            }
        }
    }

 C#中,凡是继承了IDisposable接口的类,都可以使用using语句,语句块结束后,系统自动调用Dispose()方法。
    一个资源安全的类,都继承和实现IDisposable接口和析构函数。这样就保证了手动释放和系统自动释放的双保险。

 

 

Github位置:

https://github.com/HymanLiuTS/CSGroup

克隆本项目:

Git clone git@github.com:HymanLiuTS/ CSGroup.git

获取本文源代码:

git checkout CSL06

 



相关推荐

评论