繁体   English   中英

线程内存泄漏

[英]Thread memory leak

我试图在更大的C#程序中追踪内存泄漏,该程序产生多个线程。 在这个过程中,我创建了一个小方程序,我用它来测试一些基本的东西,我发现了一些我真的不明白的行为。

class Program
{
    static void test()
    {
    }

    static void Main(string[] args)
    {
        while (true)
        {              
            Thread test_thread = new Thread(() => test());
            test_thread.Start();
            Thread.Sleep(20);
        }
    }
}

运行这个程序,我看到程序的内存使用量稳步增加而没有停止。 在短短几分钟内,内存使用量超过100MB并继续攀升。 如果我注释掉test_thread.Start();行,那么程序使用的内存最大可以达到几兆字节,并且会升级。 我还尝试使用GC.Collect()在while循环结束时强制进行垃圾收集,但它似乎没有做任何事情。

我认为一旦函数完成执行允许GC拖动它就会取消引用该线程,但这似乎并没有发生。 我不能在这里深入理解更深层次的东西,我将非常感谢帮助解决这个问题。 提前致谢!

这是设计使然,您的测试程序应该显示内存使用失控。 您可以从Taskmgr.exe中查看基本原因。 使用View + Select Columns并勾选“Handles”。 观察您的过程的句柄数量是如何稳步增加的。 内存使用量随之增加,反映了句柄对象使用的非托管内存。

设计选择非常勇敢,CLR每个线程使用5个操作系统对象。 管道,用于同步。 这些对象本身是一次性的,设计选择是不要使Thread类实现IDisposable。 这对.NET程序员来说非常困难,很难在正确的时间调用Dispose()。 在任务类设计中没有表现出来的勇气,导致大量的手工拧干和一般建议不要打扰

不是通常一个精心设计的.NET程序有问题。 GC运行的频率足以清理那些OS对象。 并且Thread对象正在谨慎创建,使用ThreadPool进行非常短的运行线程,就像测试程序使用的那样。

它可以,我们看不到你的真实节目。 请注意从这样的综合测试中得出太多结论。 您可以使用Perfmon.exe查看GC统计信息,让您了解它是否经常运行。 一个体面的.NET内存分析器是首选的武器。 GC.Collect()是备用武器。 例如:

static void Main(string[] args) {
    int cnt = 0;
    while (true) {
        Thread test_thread = new Thread(() => test());
        test_thread.Start();
        if (++cnt % 256 == 0) GC.Collect();
        Thread.Sleep(20);
    }
}

而且你会看到它现在来回反弹,永远不会超过4 MB。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM