.NET垃圾收集行为(使用DataTable obj)

gma*_*mac 3 c# memory datatable garbage-collection

我想知道为什么在创建一个非常简单的DataTable然后将其设置为null后,垃圾收集不会清除该DataTable使用的所有内存.这是一个例子.变量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);
}
Run Code Online (Sandbox Code Playgroud)

给出以下结果.

Before = 388116
After = 731248
Removed = 530176
Collected = 530176
Run Code Online (Sandbox Code Playgroud)

Kei*_*thS 5

几个原因:

GC运行在自己的甜蜜时间; 通常当运行时内存不足时.这就是为什么像DB连接那样处理对象很重要; 是的,他们最终会被释放,但直到GC才能运行.

GC.Collect()不直接运行GC线程; 它安排了一系列的GC.同样,运行时通常只在它注意到沙箱变得混乱或者有大量空闲时间时才运行GC.GC.Collect()是一个覆盖,其行为与发生其中一个自动触发器的行为相同.它不是内联调用来运行垃圾收集算法; 这将导致明显的性能下降.

GC在自己的线程中运行.因此,GC静态方法提供的信息基于调用者在调用时可用的内容.您在GC仍在工作时,或者甚至在它开始之前最后一次调用GetTotalMemory,因此内存数字尚未更新GC正在最终确定的内容.

总之,GC的设计主要是放手.GC.Collect()相当于挂在酒店门口的"请服务"标志; 这是一个建议,也许现在是清理的好时机.


Dav*_*vid 1

.NET 上的垃圾收集文档始终声明它不保证垃圾收集何时发生。

\n\n

http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

\n\n

http://msdn.microsoft.com/en-us/library/ee787088.aspx

\n\n

http://www.simple-talk.com/dotnet/.net-framework/understanding-garbage-collection-in-.net/ - - 这是一篇很好的文章,用漂亮的图表解释了垃圾收集,使其更容易理解。

\n\n

摘自与您的问题相关的最后一篇文章:

\n\n
\n

如果对象具有终结器,则当垃圾收集器决定它不再\xe2\x80\x98live\xe2\x80\x99 时,它不会立即被删除。相反,它会成为一种特殊类型的根,直到 .NET 调用终结器方法。这意味着这些对象通常需要多个垃圾收集才能从内存中删除,因为它们将在第一次被发现未使用时存活下来。

\n
\n