以下代码是我看到的问题的简化示例。由于字典太大,此应用程序在引发异常之前消耗了大约 4GB 的内存。
class Program
{
static void Main(string[] args)
{
Program program = new Program();
while(true)
{
program.Method();
Console.ReadLine();
}
}
public void Method()
{
WasteOfMemory memory = new WasteOfMemory();
Task tast = new Task(memory.WasteMemory);
tast.Start();
}
}
public class WasteOfMemory
{
public void WasteMemory()
{
Dictionary<string, string> aMassiveList = new Dictionary<string, string>();
try
{
long i = 0;
while (true)
{
aMassiveList.Add(i.ToString(), "I am a line of text designed to waste space.... I am exceptionally useful........");
i++;
}
}
catch(Exception e)
{
Console.WriteLine("I have broken myself");
}
}
}
这一切都符合预期,尽管我们目前无法确定何时应该从 CLR 中释放此内存。
我们已经让任务完成,然后模拟了内存过载的情况,但是字典消耗的内存没有释放。由于操作系统内存不足,是不是对CLR施加压力以释放内存?
然而,更令人困惑的是,如果我们等到任务完成,然后按回车键再次运行任务,内存就会被释放,那么显然之前的字典已经被垃圾回收了(不是吗?)。
那么,为什么内存没有被释放呢?我们怎样才能让 CLR 释放内存呢?
任何解释或解决方案将不胜感激。
编辑:在回复之后,特别是贝斯卡的回复,很明显我对这个问题的描述不是最清楚的,所以我会尽量澄清。
代码可能不是最好的例子,对不起!尝试复制该问题是一段快速粗略的代码。
这里使用字典来复制我们有一个大型自定义数据对象的事实,它填充了我们的一大块内存,并且在任务完成后它不会被释放。
在示例中,字典填充到字典的限制,然后引发异常,它不会永远填充!这远远早于我们的内存已满,并且不会导致 OutOfMemoryException。因此结果是内存中有一个大对象,然后任务完成。
此时,我们希望字典超出范围,因为任务和方法“方法”都已完成。因此,我们希望字典被垃圾收集并回收内存。实际上,在再次调用“方法”之前不会释放内存,创建一个新的 WasteOfMemory 实例并开始一个新任务。
希望这能稍微澄清一下这个问题