【问题标题】:DataGridViewRow not being Garbage CollectedDataGridViewRow 没有被垃圾收集
【发布时间】:2009-10-07 18:23:52
【问题描述】:

我有一个通过数据绑定对象定期填充的 DataGridView,并且行数可能会变大,例如在“记录周期”期间有数千行。

当新的“记录周期”开始时,网格会被清除,因为底层数据源已被清除,并且该过程再次开始。

这一切都很好,但是因为之前的运行需要一些时间,所有之前的行都变成了第 2 代对象,并且只有在完整 GC 上进行垃圾收集。

但是,需要两次完整的 GC 才能清除它们,因为第一个将它们全部发送到终结器队列。这意味着它们占用内存的时间是原来的两倍。

使用反射器,我看到 DataGridViewRow 没有终结器方法,但它确实继承自 DataGridViewBand 对象,它确实 - 它通过它的公共 Dispose() 方法调用 GC.SuppressFinalize(this)。

所以我的问题是 - 为什么我的 DataGridViewRows 没有在第一次完整 GC 时被收集并进入终结器队列等待另一个?

(我在这里的假设是,任何没有终结器的对象都不应该被放入终结器队列中,并且任何有终结器但调用 GC.SuppressFinalize 的对象也不会被放置在队列中。我在这个假设上是对的吗?)

谢谢。

【问题讨论】:

    标签: .net winforms memory-management datagridview finalizer


    【解决方案1】:

    GC.SuppressFinalize(this) 的调用实质上是告诉GC 在终结期间发生的清理行为已经发生(通过对Dispose() 的调用)并且它不需要再次执行终结。这与对象是否放入终结队列无关。

    任何时候实例化可终结对象 (newed),它都会被放入终结队列中。最终队列仅在每次完整 GC 收集(Gen2 收集)期间处理。可终结对象的问题之一是,它们在被实际收集之前会在至少一个额外的 GC 周期中存活。

    【讨论】:

    • 谢谢斯科特,所以看来我的理解有些缺陷?行从具有 Finalize 方法的对象继承的事实意味着它将始终放置在队列中并受制于双 GC 以清除它,我所看到的是否正确?哎哟!
    • @Andy:是的,你的理解不正确。由于DataGridViewRow 继承自可终结对象,因此它实际上也成为可终结对象并被放置在队列中。你所看到的是正确的。 Clear() 方法很可能也不会处理行,在这种情况下,您可以在调用 Clear() 之前(或之后)手动处理它们,尽管我不确定这是否可能。 (这将取决于事情是如何实现的。)或者,您可以在底层数据源上调用Dispose(),这可能也可以工作。
    • 嗯,很有趣。我曾尝试调用 Clear(),但由于“无法清除数据绑定网格”而出现错误,主要是因为数据绑定负责填充/取消填充,这似乎很公平。没想到在数据源上调用 dispose,还是试试吧。
    • 似乎什么也没做,所以我认为它必须是这样。
    • @Andy:我怀疑处理底层数据源不会产生任何影响,但值得检查以防万一。您看到的行为与可终结对象非常一致,尤其是当无法对它们调用 Dispose() 时。这只是避免使对象可终结的众多原因之一,除非有非常很好的理由这样做。
    【解决方案2】:

    如果您不处置您的对象,那么它们将不会被抑制。

    【讨论】:

    • 我同意,但我不直接创建行,它们是通过数据绑定创建的。我还需要以某种方式调用 dispose 吗?
    猜你喜欢
    • 2013-10-18
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多