首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C# Dispose() -clarification

C# Dispose() -clarification
EN

Stack Overflow用户
提问于 2010-04-02 19:31:21
回答 4查看 744关注 0票数 3

当我调用CLR时,object.Dispose()是立即从内存中销毁对象,还是在下一个周期中将对象标记为删除?

我们在Dispose()之后立即调用GC.SuppressFinalize(),这是否意味着“不要再为dispose收集对象,因为它已经提交给displose了”。

实际上,哪一代人应该对破坏负责,我猜是第二代。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-04-02 19:44:37

首先,IDisposable.Dispose和GC不是一回事。

GC将清理内存使用,IDisposable.Dispose用于确定地释放资源,如文件句柄、数据库连接、网络连接等。

让我们先来解决最终的问题。

如果一个对象声明了一个终结器,那么当GC将其从内存中释放出来时,该对象会被特殊对待。对象不是立即被释放,而是放在一个单独的列表中。

在后台,finalization线程正在运行此列表,并调用此列表上的对象的终结器方法。一旦调用了finalizer方法,该对象就会从列表中移除。

这里的要点是,当对象在此列表中时,它不符合收集的条件。这意味着,具有终结器的对象一旦符合收集条件,将临时转换为不再符合收集条件的状态,但等待完成。一旦对象再次被发现,在终结器运行并从列表中删除它之后,它将从内存中释放。

GC.SuppressFinalize只是一个对象声明“终结器不再需要运行,如果你发现这个对象符合收集条件,就立即释放它”的一种方式。

另一方面,IDisposable.Dispose一旦由对象实现,就不完全与垃圾收集器相关。GC系统中没有内置任何东西来确保调用Dispose方法。这意味着在不调用Dispose的情况下,可以轻松地释放具有Dispose方法的对象。

此外,调用Dispose也不会以任何方式使对象符合收集的条件。使对象符合收集条件的唯一方法是删除对它的所有强引用,通常是通过让局部变量超出作用域(方法返回)或通过从其他对象(如列表、事件处理程序等)中删除对该对象的任何引用。

“链接”,如果你想调用它,那就是,如果资源是非托管的,那么在内部拥有这样一个资源的对象通常会实现终结器。如果资源是托管资源,如FileStream对象,则该对象将在需要时自行处理终结。但是,如果您持有非托管资源,比如通过P/Invoke检索到的文件句柄,那么您应该实现终结器。

通常,该对象的终结器和IDisposable.Dispose都会清理该资源,然后Dispose通常会调用GC.SuppressFinalize来说:“我已经处理好了,如果对象符合收集条件,您可以释放它。”

但是,如果只调用Dispose,但仍然保留对对象的引用(事件处理程序、静态字段、局部变量等)。则该对象还不符合收集的条件,并且不会被释放。

所以,总结一下:

  1. 调用Dispose通常是为了释放资源(非托管或托管)。它不会以任何方式影响GC是否可以收集对象或何时收集对象。
  2. 使对象符合收集条件的唯一方法是显式丢失对它的所有强引用。
  3. 终结器由GC调用,通常由GC实现以释放符合收集条件但具有终结器的非托管

对象,在执行终结器之前,终结器将暂时放在列表中(因此不再适合收集

奖金问题

如果出现以下情况,您认为会发生什么:

  1. 终结器挂起?(通常(据我所知)只有一个终结器线程,如果它挂起了,那么该列表上的其他对象会发生什么?)
  2. 一个对象使自己不适合作为终结器的一部分进行收集(通常是通过将其自身插入到静态字段中)。终结器已经运行,并且有一个标记,因此一旦对象再次可供收集,终结器将不会自动重新运行。不过,GC对象中还有其他方法可以重新注册它以进行终结化。

希望这回答了你的问题,如果没有,请留下评论或澄清你的问题,我会编辑我的答案。

票数 11
EN

Stack Overflow用户

发布于 2010-04-02 19:35:48

CLR是一个通常会调用GC.SuppressFinalize的普通Dispose方法。垃圾收集器与此无关,并且调用Dispose对GC没有特殊意义。

如果Dispose调用GC.SuppressFinalize(this),则GC在收集对象时不会运行终结器。

然而,这并不意味着对象将被更快地收集。

票数 4
EN

Stack Overflow用户

发布于 2010-04-02 19:40:55

不,Dispose不会导致垃圾回收器收集对象。您在许多Dispose方法中看到GC.SuppressFinalize()的原因是因为许多可处置类实现了终结器来确保处置。我会解释的。

如果我实现了一个包含关键资源的类,并且我想确保(好吧,几乎可以肯定)我的类得到了正确的处理,那么我可能不会仅仅依赖类的使用者来调用Dispose或使用using。相反,我可能会实现一个终结器,在大多数情况下,它将在GC收集我的对象时被调用。在终结器中,我将强制调用Dispose

但是对于垃圾收集器来说,带有终结器的对象更加复杂。它将挂起更长时间,占用更多内存,并且在收集时需要更多时间进行处理。

因此,如果用户确实记得正确处理,那么我们可以告诉GC,它不需要调用此对象的终结器。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2566377

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档