【问题标题】:Do variables that reference an object that is stored in a Session variable get collect by GC?引用存储在 Session 变量中的对象的变量是否会被 GC 收集?
【发布时间】:2011-04-13 13:07:58
【问题描述】:

我不太熟悉垃圾收集的工作原理以及导致内存泄漏的原因。但我的观点是我开始关注它并想要编写更高效的代码。因此,我正在处理的项目是一个 Asp.Net Web 应用程序,当 Session 在 global.asax 中启动时创建一个自定义 DataCriteria 的实例,然后将其存储在 Session 变量中。这个自定义的 DataCriteria 是我们用来与数据库通信的 CRUD 方法。

第一个问题是,假设我们有一个 Person 类,在这个 Person 类中有一个 DataCriteria 字段,该字段设置为 DataCriteria 的 Session 变量实例。由于 Person 的实例持有对 DataCriteria 实例的引用,该实例在 Session 结束之前不会被处理,因此该 Person 的实例是否能够被收集。或者在 Session 结束之前不会处理 Person 的每个实例。

第二个问题更笼统,但问题相同。基本上我想知道在引用 DataCriteria 的 Session 变量实例的方法中声明的变量是否能够被 GC 收集?还是会一直持续到 Session 结束?

感谢您在这里给我的所有建议。如果您知道任何有助于理解垃圾收集和避免内存泄漏的好读物,我也很想听听。

【问题讨论】:

    标签: c# memory-management garbage-collection


    【解决方案1】:

    对象持有的引用不会影响其垃圾回收的可用性。然而,反之亦然。例如,假设一个实例 A 有一个包含实例 B 的字段。只要没有其他东西引用它,A 就可以用于垃圾回收,即使 B 是静态的或以其他方式“长期存在”。但是,在 A 可用于垃圾回收之前,B 将无法用于垃圾回收至少

    事情可能会变得有点奇怪的地方是参考不太明显。例如,当 C 订阅 D 公开的事件时,实例 C 将被实例 D 引用。这意味着,如果 D 是长期存在的,则 C 在 D 之前将无法用于垃圾收集,除非它取消订阅该事件。通过事件和其他委托持有的引用实际上是 .NET 应用程序中大部分“内存”泄漏的原因。 (正确地说,这些并不是真正的内存泄漏,因为在清理实际对象实例未使用的内存时没有实际失败。)

    【讨论】:

    • 谢谢,这是一个很好的答案。我实际上是要询问事件处理程序。那么如果实例 C 订阅了它自己的事件呢?您是否应该在 Dispose 方法中取消订阅这些。或者这只是不需要? Dispose 方法中是否只需要处理其他引用事件的订阅?
    • 自引用不会使对象保持活动状态。 (类似地,一组实例之间没有被其他任何东西引用的引用也不会使它们中的任何一个保持活动状态。)这意味着不需要取消订阅自己的事件。 (也就是说,订阅自身事件是在实例中触发操作的一种相当昂贵的方法。)在对象的 Dispose 方法中,只需要清除自己的事件并取消订阅其他对象上的事件。
    • 所以如果我的 Person 类继承了另一个实现 INotifyPropertyChanged 接口的类。 Person 实例具有 PropertyChanged 事件的处理程序。那是我应该在 Dispose 中取消订阅的处理程序吗?我想我需要一个实际的例子来清楚地理解它。
    • Person 实例不需要取消订阅其自己的 PropertyChanged 事件,无论该事件是在 Person 还是在其基类之一中声明的。但是,如果 Person 类具有 Person 类型的 Child 属性,并且 Person 实例订阅了其 Child 上的事件,并且 Child 实例的寿命可能比父实例长,则父实例应在处置期间取消订阅 Child 事件。跨度>
    • 好吧,这是有道理的。我很欣赏这个解释。现在我想我最好去删除一些不需要的代码。再次感谢。
    【解决方案2】:

    对象引用构成一个有向图——对象A引用对象B。在A被收集之前,B不能被收集。

    Session 只是另一个引用东西的对象 - 在这种情况下,它是对象 A 引用您的对象 B。

    所以在你的情况下,仅仅因为 Person 引用了也存储在 Session 中的东西并不意味着 Person 会一直存在直到 Session 消失。除非 Session 引用您的 Person,否则它们的生命周期不会关联。

    现在您需要注意的是您的 DataCriteria 引用的其他内容。如果它持有数据库连接或其他对象,它们将与 Session 一样长。

    【讨论】:

    • 感谢您的回答。你们对此非常有帮助。我也会将您的答案标记为答案,但她包括了那个事件处理程序部分。但无论如何,非常感谢您澄清这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多