在c#中显式释放内存

我创build了ac#应用程序,占用了150MB的内存(专用字节),主要是由于一个大字典:

Dictionary<string, int> Txns = new Dictionary<string, int>(); 

我想知道如何释放这个内存。 我试过这个:

 Txns = null; GC.Collect(); 

但是,我的私人字节似乎并没有太大的影响 – 从155mb降到145mb。 任何线索?

谢谢

-编辑-

好吧,我有这个代码更多的运气(它获得私人字节下降到50MB),但为什么?

 Txns.Clear(); // <- makes all the difference Txns = null; GC.Collect(); 

-编辑-

对于那些说'不要使用GC.collect'的人来说,没关系(我不打算讨论这个问题,除了说你可以看到我的C背景通过),但是它并没有真正回答我的问题:为什么垃圾收集器只有在清除事务列表时才释放内存? 不pipe怎样,它不应该释放内存,因为字典已经取消了?

专用字节反映进程的内存使用情况。 当收集对象时,关联的内存段可能会或可能不会被释放到操作系统。 CLR在操作系统级别pipe理内存,因为分配和释放内存不是免费的,所以没有理由立即释放每一块内存,因为应用程序可能稍后会请求更多的内存。

如果你调用GC.Collect()它开始做它的工作,但它立即返回,它不阻止,所以你不看到它的影响,如果你只是调用GC.WaitForPendingFinalizers()之后,它会阻止你的应用程序,直到GC。收集()完成它的工作

很可能你在其他地方有隐藏的字典引用。 因此,字典不收集,但如果你Clear()它收集的内容。

正如其他人已经指出,不推荐强迫GC。 这可能导致记忆被推向更高的“世代”,这往往是不被收集的,从而浪费了比长期增加的更多的记忆。

从内存不确定如果Dictionary有一个Dispose()或没有,但它必然有一个Clear() 。 在将任何引用设置为null之前调用其中之一。

然后,简单地让垃圾收集器做它的工作。 调用GC.Collect()几乎不是一个好主意,它甚至可能不会做你想要/期望的事情,最终导致性能下降。 静态代码分析(= FxCop)没有警告可靠性规则CA2001关于这个没什么,你知道吗? 除非你真的知道你在做什么,否则不要这样做。 即使如此,也不要这样做。 😉

你确定字典是那么大吗? 是不是只有10 Mb的内存,其余的是由你的应用程序? 可能对你有帮助的问题:你有没有使用一个分析器来查看内存在哪里被消耗…?

编辑:

公平地说,将引用设置为null不会释放内存,它会将容器分配给不同的地址,在这种情况下为null。 根据MSDN ,调用Clear() ,这样做:“Count属性设置为0,从集合中的元素引用其他对象也释放,容量保持不变。

你不应该调用垃圾收集器。 您正在使用没有本地资源的托pipe对象,请相信垃圾收集器在您之后清理。

除了你的字典的大小,你不需要担心内存,内存不是你的问题,这是垃圾收集器的问题。

调用Clear()将删除对任何包含对象的引用,但容量保持不变。

在技​​术上,收集内存是昂贵的,并且相当耗时的操作。 原因在于,GC不仅处理堆内存并清理堆,而且还对堆进行碎片整理。 它试图将内存移动到连续的块中,以便在某些代码发出大量请求时加快分配。

ps你的字典有多大,你使用155MB的内存?

你需要回忆吗? 内存是可用的,它只是没有被回收。 你不应该清除字典,只要对它做一个弱引用 ,让运行时就可以完成它的工作。

如果您想深入了解发生了什么,请查看.NET Memory Profiler 。 这会让你清楚地知道你的对象究竟发生了什么,它是什么样的一代,正在被什么使用什么内存。 🙂

好的,我在这里有一个理论… Dictionary是KeyValuePair的集合,它又是一个引用types。

你的字典包含这些keyValuePairs。 当你说:

 Txns = null 

它从这些KeyValuePair集合中释放引用“Txns”。 但是150Mb的实际内存仍被这些KeyValuePair所引用,它们在范围之内,因此没有准备好进行垃圾回收。

但是,当你使用以下内容:

 Txns.Clear(); Txns = null; GC.Collect(); 

在这里,清除方法也从各自的KeyValuePair对象引用中释放150Mb的数据。 因此这些对象已经准备好进行垃圾收集。

这只是一个疯狂的猜测,我在这里。 欢迎评论:)

Windows有两个内存可用性事件。 我希望CLR对此作出回应。 如果有足够的内存,聪明的是不要运行垃圾收集器。 因此,为了确保您确实观察到了错误的CLR行为,请使用另一个虚拟应用程序使用大量内存来重复此testing。

试图强制GC通常不是一个好主意。 你真的需要把整本字典放在记忆里吗?