方法结束后,内存保持分配

时间:2017-03-31 10:43:30

标签: c# memory memory-leaks garbage-collection

我正在使用C#和.NET Framework 4.6.2以及Entity Framework 6.1.3开发Windows服务。

我在该服务上有一个Web API接口,在一个Controller的方法中,我创建了一个包含超过一百万个字符串的字典:

Dictionary<string, List<string>> codes;

此词典在另一个方法中创建:

codes = GetCodesAsDictionary(connectionString, productionId);

我将此变量传递给静态类中的静态方法。

一个Visual Studio 2015的内存分析器我看到当我调用此方法时内存增长到1,1Gb,但是当方法结束时,内存保持为1,1Gb。

如果我再次调用该方法,则内存再次增长到2Gb,并且在方法完成后,内存再次变为1,1Gb。

我试图将codes变量作为参考传递,但我获得了相同的内存分配。我必须停止服务并重新运行它以释放1,1Gb。顺便说一句,我通过引用传递它,因为我不希望静态方法复制它。

你知道为什么在方法结束后它没有释放这么多的内存吗?

更新

我用实例类更改了静态类(从静态类复制方法),我得到了相同的结果(分配了1,1Gb内存)。

第二次更新:

我还改变了字典的创建方式:

Dictionary<string, List<string>> codes = null;
GetCodesAsDictionary(connectionString, productionId, out codes);

我得到了相同的结果:分配了1,1Gb内存。

第三次更新
我用Dictionary更改了KeyValuePair<byte, string[]>[],我得到了相同的结果,分配了1,1Gb。现在,我没有使用string作为键,而是使用byte。

2 个答案:

答案 0 :(得分:0)

  

你知道为什么在方法结束后它没有释放这么多的内存吗?

如果还没有任何参考文献,那可能就是垃圾收集者没有感觉到释放内存的冲动,即使它已经不再使用了

您可以尝试force garbage collection并查看是否释放了内存。如果没有,您的代码可能存在问题。

(旁注:如果你在字符串中有大量的重复,你可能会因为实习而受益。它会大大减少内存压力。但是这样可以随时分配这些字符串。)

答案 1 :(得分:0)

您确定在该方法中创建并使用 字典吗?

如果没有其他帮助,您可以尝试使用GC.Collect(),但这应该仅用作最后的手段。

https://msdn.microsoft.com/en-us/library/system.gc.collect(v=vs.110).aspx

编辑:您可以尝试使用GC.AddMemoryPressure方法而不是我之前建议的方法。您需要传递内存量以使GC意识到可以收集一些内存这一事实。

https://msdn.microsoft.com/en-us/library/system.gc.addmemorypressure(v=vs.110).aspx

尝试以下方法适用于您:

Dictionary<string, List<string>> codes = new Dictionary<string, List<string>>();
long bytesBefore = GC.GetTotalMemory(true);

// Code that adds items to your dictionary comes here

long bytesAfter = GC.GetTotalMemory(true);

// After your method ends:
GC.AddMemoryPressure((long) (bytesAfter - bytesBefore));