我是如何解决这个内存泄漏问题的?

Dan*_*dor 3 .net c# memory-leaks .net-2.0

我有一个.net 2.0应用程序,它做了一些繁重的处理,使用大量的内存,并做了一些.它从Web服务中获取任务,完成任务,返回结果,并将所有内容重复到无穷大.

由此可以简化和说明主代码结构

while (true) 
{
     Task t=ServiceAccess.GetTask();
     if (t.TaskType == 1)
     {
          BrutalMemoryConsumerProcessor b=new BrutalMemoryConsumerProcessor();
          b.DoTask(t);
     } 
     else if (t.TaskType == 2)
     {
          HeavyCPUConsumerProcessor h=new HeavyCPUConsumerProcessor();
          h.DoTask(t);
     }
}
Run Code Online (Sandbox Code Playgroud)

幸运的是,它OutOfMemoryException在内部代码的某个地方经过几个周期后就死了.这是因为两个对象都经过校准,几乎可以使用所有的RAM(对于x86应用程序),并且在创建新对象实例时使用旧对象实例是一个可靠的方法来消除进程.

好的,所以我先尝试了一些技巧.即:

GC.Collect();
Run Code Online (Sandbox Code Playgroud)

在循环开始时,就在之后while (true).

没运气.

接下来,我想起了老VB6基于COM的日子,并试图b = null;h = null;该范围内的if语句块.

没有运气了.

结合,没有骰子.

解雇了一个内存分析器.我有一段时间没有使用它,所以我需要浏览几页"程序文件"才能找到它.它是YourKit Profiler.好玩具......

无论如何,在经过一些干预后,它告诉我引用bh保留在本地"堆栈范围"内.所以我做了猴子会做的事情,并在上面重写为:

while (true) 
{
     Task t=ServiceAccess.GetTask();
     if (t.TaskType == 1)
     {
          DoTaskType1(t);
     } 
     else if (t.TaskType == 2)
     {
          DoTaskType2(t);
          HeavyCPUConsumerProcessor h=new HeavyCPUConsumerProcessor();
          h.DoTask(t);
     }
}

private void DoTask1(Task T)
{
    BrutalMemoryConsumerProcessor b=new BrutalMemoryConsumerProcessor();
    b.DoTask(T);
}

private void DoTask2(Task T)
{
    HeavyCPUConsumerProcessor b=new HeavyCPUConsumerProcessor();
    b.DoTask(T);
}
Run Code Online (Sandbox Code Playgroud)

我的.它解决了内存泄漏问题.

因此,通过将对象创建移动到肯定会超出范围的函数中,尽管if代码块本身就是范围,但对象已被释放并被删除.

为什么?

usr*_*usr 5

您可能未经优化运行(在调试模式下,或附加调试器).在这种情况下,JIT将本地生命周期延长到方法的末尾,以帮助调试.

使用单独的方法,本地人只存在于一个快速消失的单独堆栈框架中.

在没有调试器的发布模式下尝试它.