【问题标题】:Is it possible to manually mark/unmark an object for garbage collection?是否可以手动标记/取消标记垃圾收集的对象?
【发布时间】:2014-04-29 01:10:56
【问题描述】:

大多数资源都表明垃圾收集器会根据引用自行计算出来,我不应该搞砸它。

我想知道是否可以明确告诉垃圾收集器它可能在释放对象的同时仍保留引用。

我想做的是告诉垃圾收集器我目前不再需要一个对象(但可能会再次),然后在稍后(如果)我再次需要该对象时我想检查如果它已经被处置。如果有,我只需重新创建它,如果没有,我想从垃圾收集中“取消标记”它,直到我再次完成它。

这可能吗?

我计划实现类似于Lazy<T> 类的东西。伪代码:

obj = new DisposeIfNecessary<LargeObject>(() => InitLargeObject());
obj.DoSomething(); // Initializes obj using InitLargeObject()
obj.DisposeIfNecessary(); // This is where the magic happens

... // obj might get disposed at some point

obj.DoAnotherThing(); // Might or might not call InitLargeObject() again
obj.Dispose(); // I will not need it again

【问题讨论】:

  • 不是“大多数资源”,所有资源。 Dispose() 与垃圾收集无关。如果您处置了一个对象并且您想在之后使用它,那么您做错了。只是不要丢弃它。

标签: c# garbage-collection weak-references


【解决方案1】:

WeakReference 类完全符合您的要求,使用 IsAlive 属性在使用前检查状态。

您可以通过Target 属性再次获得对其的“强”引用,这将影响引用计数并使其无法被收集。

还请注意,Dispose 与垃圾回收没有直接关系,因此处置一个项目(取决于Dispose 实现)可能会使其无法使用 - 但同样,这与 GC 无关。正如@HansPassant 所提到的,在一般实践说明中,在一个项目(或通常声称要处理的任何东西)上调用Dispose,然后尝试再次使用它是一种代码异味(或者就像其他开发人员所期望的那样完全错误@ 987654328@ 是一个最后调用方法,从那时起将对象标记为不可用)。

WeakReference 类将不负责重新创建收集的对象,但与IsAlive 一起,您可以自己处理该逻辑。

此外,就 cmets 而言,GC 在决定何时收集 WeakReference 方面并没有做任何聪明的事情,试图将 WeakReference 项目留到最后;如果它符合条件,它将像在运行期间收集其他对象一样收集底层对象 - 没有特殊处理,绝对没有“缓存”行为。

【讨论】:

  • 请注意,WeakReference 不是缓存,不是“绝对需要就扔掉”,而是“你可以检查它是否被扔掉”。
  • @LasseV.Karlsen 啊,我会修改我的答案以涵盖您的观点。
  • 谢谢,这正是我想要的!我会接受答案,但是虽然这确实解决了我的问题,但它并没有真正回答原来的问题...... @Lasse:我确实在寻找一个只在确实有必要时才删除对象的缓存。您对我将如何实现这一目标有更好的想法,还是您也会选择WeakReference
  • @RomanReiner 就我从你原来的问题中可以看出,它解决了两点:检查对象,如果你需要创建它,或者如果它没有被 GC 阻止它还没有。您实际上根本没有在问题中提及任何缓存语义......
  • WeakReference 绝不会阻止收集“引用”对象。它只允许您检索对对象的引用如果它还没有被收集。让我重述一下。只有一个对象的 WeakReference 不会以任何方式影响垃圾收集器。如果对象在你没有 WeakReference 的情况下会被收集,那么即使你有一个也会被收集。所以基本上,它不是“直到绝对需要收集的缓存”。然而,我不知道任何这样的类或构造,尽管这绝对不是说没有。我只是不知道。
猜你喜欢
  • 2011-02-08
  • 1970-01-01
  • 2011-07-16
  • 1970-01-01
  • 2010-11-17
  • 1970-01-01
  • 2018-10-30
  • 2018-06-10
  • 1970-01-01
相关资源
最近更新 更多