2009-10-07 69 views
1

我有一个DataGridView正在定期通过数据绑定对象填充和行数有可能变大,一个“记录周期”中说成千上万。的DataGridViewRow不被垃圾收集

当一个新的“记录周期”开始,因为底层数据源被清除网格被清除,过程又重新开始。

这是所有罚款,但因为之前的运行需要一定的时间,所有这些以前的行成为2代对象,只收集一个完整的GC垃圾。

但是,它需要两个完整GC的清除它们,因为第一个他们都发送到终结队列中。这意味着他们周围的时间长达两倍的时间。我发现DataGridViewRow没有一个终结器方法,但它确实继承了DataGridViewBand对象,它通过它的公共Dispose()方法调用GC.SuppressFinalize(this)。

所以我的问题是 - 为什么我的DataGridViewRows没有得到收集了第一个完整的GC,并使其到终结队列中等待下一次呢?我在这里假设没有终结器的任何对象不应该被放置到终结器队列中,任何有一个但调用GC.SuppressFinalize的对象也不会放在队列中。假设?)

谢谢。

回答

3

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

在任何时间一个终结对象被实例化(new编),它被放置在终止队列。完成队列仅在每个完整GC采集(Gen2采集)期间处理。可终结对象的问题之一是它们在实际收集之前将经历至少一个额外的GC循环。

+0

谢谢Scott,所以看起来我的理解有点瑕疵?事实上,一个行使用Finalize方法从一个对象继承意味着它将始终放在队列中,并受到双重GC的清除,我所看到的是正确的?哎哟! – Andy 2009-10-07 19:37:55

+1

@安迪:是的,你的理解是不正确的。由于'DataGridViewRow'继承自可终结对象,因此它实际上也成为可终结对象,并被放置在队列中。你所看到的是正确的。 Clear()'方法很可能不会处理行,在这种情况下,您可以在调用Clear()之前(或之后)手动处理它们,尽管我不确定这是否可行。 (这取决于实现的方式。)或者,您可能可以在底层数据源上调用Dispose(),这可能也会起作用。 – 2009-10-07 19:42:46

+0

嗯,有趣。我曾尝试调用Clear(),但由于'无法清除数据绑定网格',我得到错误,本质上是因为数据绑定负责填充/清除这似乎足够公平。虽然没有想过在数据源上调用dispose,但会放弃它。 – Andy 2009-10-07 19:48:47

0

如果你不处理你的对象,那么它们将不会被终止。

+0

我同意,但我不直接创建行,它们是通过数据绑定创建的。我还需要以某种方式调用它们吗? – Andy 2009-10-07 19:22:50