Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# GC是否可能在IDisposable实现的类的析构函数中调用?_C#_.net_Memory_Memory Leaks_Garbage Collection - Fatal编程技术网

C# GC是否可能在IDisposable实现的类的析构函数中调用?

C# GC是否可能在IDisposable实现的类的析构函数中调用?,c#,.net,memory,memory-leaks,garbage-collection,C#,.net,Memory,Memory Leaks,Garbage Collection,-----------编辑1---------- 对不起,我的英语很差,原来的问题对很多人来说似乎没有意义,所以我把问题简化为两句话: 在的msdn代码示例中,将释放未管理的资源代码放入析构函数是为了当用户忘记调用Dispose()来释放资源时,GC仍然可以帮助释放至少未管理的资源,但是,当类使用一些未管理的资源时,它必须注册(隐式或显式)当前实例(或字段)到GC句柄表,然后将永远不会被GCed,那么在这种情况下如何执行析构函数中的代码呢 -----------结束编辑1------- 我们知道

-----------编辑1----------

对不起,我的英语很差,原来的问题对很多人来说似乎没有意义,所以我把问题简化为两句话:

在的msdn代码示例中,将释放未管理的资源代码放入析构函数是为了当用户忘记调用
Dispose()
来释放资源时,GC仍然可以帮助释放至少未管理的资源,但是,当类使用一些未管理的资源时,它必须注册(隐式或显式)当前实例(或字段)到GC句柄表,然后将永远不会被GCed,那么在这种情况下如何执行析构函数中的代码呢

-----------结束编辑1-------

我们知道著名的
IDisposable
模式,它可以在web上看到很多东西,比如:

据我所知,在示例中,析构函数的作用适用于这种情况:如果用户忘记显式调用
Dispose()
,那么GC将帮助并释放未管理的资源

但我只是想知道,在任何情况下,析构函数都可以被GC调用,而不需要用户代码先显式调用
Dispose()

猜测基于实现
IDisposable
的原因,并具有显式析构函数:

此类使用了一些未管理的资源。无论是通过P/Invoke还是托管API(BCL),正如我所知,这两种方法都需要向GC handle表中添加一个GC handle条目,它avoidGCed,因此析构函数永远不会被GC调用


所以我们永远不要指望资源自动释放会带来好运?为什么要把它放在示例代码中呢?

GC使用一种称为finalization的机制来处理实现了
IDisposable
的类

如果正确实现该类,那么当未调用
Dispose
时,GC将在对象超出范围时处理该对象,并且GC将调用终结器。终结器在不可预测的时间被隐式调用


更多的技术细节可以从诸如CLR via C#之类的书籍或

之类的文章中找到,GC使用一种称为finalization的机制来处理实现
IDisposable
的类

如果正确实现该类,那么当未调用
Dispose
时,GC将在对象超出范围时处理该对象,并且GC将调用终结器。终结器在不可预测的时间被隐式调用


更多的技术细节可以从诸如CLR via C#之类的书籍或诸如

之类的文章中找到,这里有很多问题。让我们试着回答所有的问题

IDisposable
模式的MSDN代码示例中,释放非托管资源的代码被放入析构函数中。这确保了当用户放弃调用
Dispose()
释放资源时,GC仍然释放非托管资源

但当一个类使用一些非托管资源时,它必须已将当前实例注册到GC句柄表,然后将永远不会被GCed

我不明白这句话。您提到的“GC句柄表”是什么

您可以展示一些示例代码来演示您的场景吗

在这种情况下,析构函数中的代码是如何执行的

简而言之,GC是这样工作的。GC知道“根”;这些参考文献绝对是活的。GC首先将所有对象标记为死对象。然后,它将这些根标记为活的。然后它将根所指的一切标记为活着,然后将它们所指的一切标记为活着,依此类推。这就是从根上可以到达的一切都是活的。然后GC杀死所有仍然标记为死亡的东西

现在,如果一个死对象是可终结的——如果它有一个尚未运行的析构函数——那么GC不会终止该对象。该对象被放在要最终确定的对象列表中,并且该列表是根,因此该对象再次处于活动状态。稍后,另一个线程运行终结队列上每个对象的析构函数,并将它们从队列中删除,并将它们标记为不再需要终结

下次GC运行时,如果对象仍然处于死区,则会收集该对象,并且不会再次运行终结器

GC是否可以在没有用户代码的情况下首先显式调用
Dispose()


对。这就是析构函数的全部要点。

这里有很多问题。让我们试着回答所有的问题

IDisposable
模式的MSDN代码示例中,释放非托管资源的代码被放入析构函数中。这确保了当用户放弃调用
Dispose()
释放资源时,GC仍然释放非托管资源

但当一个类使用一些非托管资源时,它必须已将当前实例注册到GC句柄表,然后将永远不会被GCed

我不明白这句话。您提到的“GC句柄表”是什么

您可以展示一些示例代码来演示您的场景吗

在这种情况下,析构函数中的代码是如何执行的

简而言之,GC是这样工作的。GC知道“根”;这些参考文献绝对是活的。GC首先将所有对象标记为死对象。然后,它将这些根标记为活的。然后它将根所指的一切标记为活着,然后将它们所指的一切标记为活着,依此类推。这就是从根上可以到达的一切都是活的。然后GC杀死所有仍然标记为死亡的东西

现在,如果一个死对象是可终结的——如果它有一个尚未运行的析构函数——那么GC不会终止该对象。该对象被放在要最终确定的对象列表中,并且该列表是根,因此该对象再次处于活动状态。稍后,另一个线程运行fi上每个对象的析构函数