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