从GC的SuppressFinalize方法带你深刻认识Finalize底层运行机制(GC.SuppressFinalize)

网友投稿 861 2022-09-20

从GC的SuppressFinalize方法带你深刻认识Finalize底层运行机制(GC.SuppressFinalize)

从GC的SuppressFinalize方法带你深刻认识Finalize底层运行机制(GC.SuppressFinalize)

如果你经常看开源项目的源码,你会发现很多Dispose方法中都有这么一句代码: GC.SuppressFinalize(this); ,看过一两次可能无所谓,看多了就来了兴趣,这篇就跟大家聊一聊。

一:背景

1. 在哪发现的

相信现在Mysql在.Net领域中铺的面越来越广了,C#对接MySql的MySql.Data类库的代码大家可以研究研究,几乎所有操作数据库的几大对象:MySqlConnection,MySqlCommand,MySqlDataReader以及内部的Driver都存在 GC.SuppressFinalize(this)代码。

public sealed class MySqlConnection : DbConnection, ICloneable

{

public new void Dispose()

{

Dispose(disposing: true);

GC.SuppressFinalize(this);

}

}

public sealed class MySqlCommand : DbCommand, IDisposable, ICloneable

{

public new void Dispose()

{

Dispose(disposing: true);

GC.SuppressFinalize(this);

}

}

2. GC.SuppressFinalize 场景在哪里

先看一下官方对这个方法的解释,如下所示:

//

// Summary:

// Requests that the common language runtime not call the finalizer for the specified

// object.

//

// Parameters:

// obj:

// The object whose finalizer must not be executed.

//

// Exceptions:

// T:System.ArgumentNullException:

// obj is null.

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]

[SecuritySafeCritical]

public static void SuppressFinalize(object obj);

意思就是说: 请求 CLR 不要调用指定对象的终结器,如果你对终结器的前置基础知识不足,那这句话肯定不是很明白,既然都执行了Dispose,说明非托管资源都被释放了,怎么还压制CLR不要调用Finalize呢?删掉和不删掉这句代码有没有什么严重的后果,GC类的方法谁也不敢动哈。。。 为了彻底讲清楚,有必要说一下Finalize整个原理。

二:资源管理

我们都知道C#是一门托管语言,它的好处就是不需要程序员去关心内存的分配和释放,由CLR统一管理,这样编程门槛大大降低,天下攘攘皆为利来,速成系的程序员就越来越多~

1. 对托管资源和非托管资源理解

<1> 托管资源

这个很好理解,你在C#中使用的值类型,引用类型都是统一受CLR分配和GC清理。

<2> 非托管资源

在实际业务开发中,我们的代码不可能不与外界资源打交道,比如说文件系统,外部网站,数据库等等,就拿写入文件的StreamWriter举例,如下代码:

public static void Main(string[] args)

{

StreamWriter sw = new StreamWriter("xxx.txt");

sw.WriteLine("....");

}

为什么能够写入文件? 那是因为我们的代码是请求windows底层的Win32 Api帮忙写入的,这就有意思了,因为这个场景有第三者介入,sw是引用类型受CLR管理,win32 api属于外部资源和.Net一点关系都没有,如果你在用完sw之后没有调用close方法的话,当某个时候GC回收了托管堆上的sw后,这给被打开的win32 api文件句柄再也没有人可以释放了,资源就泄露了,如果没看懂,我画张图:

三:头疼的非托管资源解决方案

1. 使用析构函数

很多时候程序员就是在使用完类之后因为种种原因忘记了手动执行Close方法造成了资源泄露,那有没有一种机制可以在GC回收堆对象的时候回调我的一个自定义方法呢?如果能实现就

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:AIX的进程管理命令
下一篇:AIX中的网络类命令
相关文章

 发表评论

暂时没有评论,来抢沙发吧~