<击>
每当我拨打GC.Collect()
或GC.GetTotalAmountOfMemory(true)
时,整个程序就会挂起。现在,我知道你要说什么:不要打电话给GC.Collect()
GC照顾自己。问题是:在我的情况下,内存中没有东西,GC无法摆脱它。
我不知道它可能是什么(项目是大/旧)。我希望有人知道如何获取有关GC尝试做什么的信息(显然不能做),以便我可以搜索问题或者像内存分析器这样的东西在这里有任何帮助(我目前有ANTS)安装)以及我应该搜索的内容。
*编辑 我完全忘记的事情:有时当我调用GC的两种方法之一时,内存使用量会增加~10千字节/秒
* EDIT2 我要纠正自己:GC.Collect()运行得很好。只有GC.GetTotalMemory(true)挂起。 GC.GetTotalMemory(false)也可以正常工作。
击><击> * EDIT3 并且就像你们中的一些人已经说过的那样:它似乎是某个地方的终结者。当我运行WaitForPendingFinalizers()时,它只是坐在那里,什么都不做。 击>
好吧,现在我完全感到困惑:当我暂停调试器后,当我在Visual Studio的即时窗口中输入GC.GetTotalMemor(true)
或GC.WaitForPendingFinalizers()
时,程序挂起(这就是什么我一直都这么做......我现在觉得很蠢)。当我将它添加到我通常的源代码并编译它时,它可以正常工作。
抱歉整个模糊,似乎记忆漏洞有另一个原因。
答案 0 :(得分:7)
你是否覆盖任何终结者?当终结器未返回时(可能您在任何时候等待另一个线程)应用程序可能会挂起。 GC.Collect()
调用终结器但它永远不会返回,因为它等待终结器返回。这可能也是导致内存泄漏的原因,因为GC无法完成垃圾回收。
你应该能够调试它,当GC收集时你按下“暂停”它应该显示它挂起的堆栈跟踪。如果一切都出错了,您可能需要检查应用程序挂起的反汇编。
此方法强制进行垃圾收集,因此它与GC.Collect()
相同。
让我们看看GetTotalMemory:
public static long GetTotalMemory(bool forceFullCollection)
{
long totalMemory = GC.GetTotalMemory();
if (!forceFullCollection)
{
return totalMemory;
}
int remainingSteps = 20;
long lastMemory = totalMemory;
float num4;
do
{
GC.WaitForPendingFinalizers();
GC.Collect();
totalMemory = lastMemory;
lastMemory = GC.GetTotalMemory();
num4 = (float)(lastMemory - totalMemory) / (float)totalMemory;
}
while (remainingSteps-- > 0 && (-0.05 >= (double)num4 || (double)num4 >= 0.05));
return lastMemory;
}
正如您所看到GetTotalMemory
正在等待终结器,因此它必须是一个挂起应用程序的终结器。终结器完成时会调用GC.Collect()
,永远不会被调用,因为它之前从未通过该行。
在你的应用程序中的任何一点(不安全的代码?另一个线程?)有一些东西分配了大量的内存,而GC从来没有机会清理现有的内存。
这是一个纯粹的猜测,我不知道GC是否处理这种情况,但我认为它不能打破终结器的执行,因为它可能需要很长时间而GC不知道他是否只是挂或者仍在最后确定。
答案 1 :(得分:2)
您是否考虑过使用服务器模式GC设置,以便每个处理器核心运行一个GC线程? 您是否使用性能计数器,转储或分析器调查了该问题? ANTS内存分析器非常有用,如果应用程序本身不会因使用它而减慢太多 我还将使用Windows Process Explorer查看您的应用程序,以了解内存方面发生的情况。