我想知道为什么在创建一个非常简单的数据表并将其设置为null之后,垃圾收集不会清除该数据表使用的所有内存。这是一个例子。变量Before应该等于Removed,但不是。

{
 long Before = 0, After = 0, Removed = 0, Collected = 0;

 Before = GC.GetTotalMemory(true);
 DataTable dt = GetSomeDataTableFromSql();
 After = GC.GetTotalMemory(true);
 dt = null;
 Removed = GC.GetTotalMemory(true);
 GC.Collect();
 Collected = GC.GetTotalMemory(true);
}


给出以下结果。

Before = 388116
After = 731248
Removed = 530176
Collected = 530176

最佳答案

几个原因:

GC在自己的美好时光中运行;通常在运行时内存不足时。这就是为什么布置诸如数据库连接之类的对象很重要的原因。是的,它们最终会被释放,但要等到GC设计运行后才能发布。

GC.Collect()不会直接运行GC线程;计划GC的运行。同样,运行时通常仅在注意到沙箱变得混乱或存在大量空闲时间时才运行GC。 GC.Collect()是一个重写,其行为与发生这些自动触发器之一的行为相同。这不是运行垃圾回收算法的内联调用;这将导致明显的性能下降。

GC在其自己的线程中运行。因此,GC静态方法提供的信息基于调用者在调用时可以使用的信息。您将在GC仍在工作时,或者甚至在它启动之前,最后一次调用GetTotalMemory,因此内存数量尚未随着GC的完成而更新。

总而言之,GC的设计在很大程度上是不实际的。 GC.Collect()等同于在您的酒店门上悬挂“ please service”标志。这表明现在也许是清理的好时机。

10-07 20:12