创建大量线程时.Net内存泄漏

Posted

技术标签:

【中文标题】创建大量线程时.Net内存泄漏【英文标题】:.Net Memory Leak when creating lots of threads 【发布时间】:2015-06-23 09:56:19 【问题描述】:

我有一个应用程序会随着时间的推移创建大量线程。我注意到内存使用量随着它的运行而增长,并最终耗尽内存。但是相同的代码不会在我同事的环境中泄漏内存。我们都有相同的 .net 版本。我能够使用以下示例代码重现该问题,该代码不会在我同事的笔记本电脑上泄漏,但会在我的笔记本电脑上泄漏。

public static void Main(string[] args)
           
    Console.WriteLine("Version " + Environment.Version.ToString());

    if (Environment.Is64BitProcess) 
        Console.WriteLine("64"); 
    else 
        Console.WriteLine("32");

    while(true)
    
        Thread t = new Thread(() =>  Thread.Sleep(1); );
        t.IsBackground = true;
        t.Start();
        Thread.Sleep(1);               
    

当我运行上述内容时,它会打印以下内容

Version 4.0.30319.18063
32

在 Visual Studio 2012 中,项目的目标框架是 .net framework 4.5。 该项目使用以下配置泄漏内存

Project Properties -> Build
    Platform target: Any CPU
    Prefer 32-bit: checked

如果我取消选中首选 32 位,它不会泄漏。

另一个泄漏内存的配置是

Project Properties -> Build
    Platform target: x86
    Prefer 32-bit: disabled

在我的笔记本电脑上泄漏的生成的可执行文件不会在我同事的笔记本电脑上泄漏。

我使用 CLR Profiler 来查找内存泄漏,但它没有显示任何泄漏。但我确实看到 Windows 资源监视器中的工作集增加了大约 1 MB/秒。

是什么导致我的环境在 32 位模式下内存使用量增加,但我同事的却没有?

【问题讨论】:

FWIW 当我在我的电脑上尝试这个时,我得到了和你同事一样的行为(没有泄漏)。 尝试使用umdh tool(确保安装适用于 Windows 的 32 位调试工具)来查看谁在分配所有内存。另外,如果你去掉线程方法里面的 sleep 会发生什么? 使用进程资源管理器或任务管理器检查线程数。它增加了吗?可能是时机。 我很高兴看到这个问题得到解决。 您过去可以使用这样的代码非常可靠地使您的程序崩溃。 Thread 类使用了很多句柄,但没有 Dispose() 方法。不再,微软对此做了一些事情。您现在需要寻找对句柄(程序员自愿安装在其机器上的收缩包装的恶意软件)过于感兴趣的其他类型的软件。禁用您的防病毒产品,然后重试。 【参考方案1】:

我已经阅读了所有的cmets,并且担心我的评论会在那里丢失,所以尝试回答。

使用专为 .NET 应用程序设计的内存分析器、JetBrains dotMemory 或 ANTS 或除 WinDBG 或任务管理器或其他本机内存工具之外的任何其他工具。

您可以使用所选分析器的实时图表来比较应用在您和您同事的笔记本电脑上的表现。 我想您会看到笔记本电脑上的内存使用量不断增加 - 只需获取内存快照并查看内存中有多少 Thread 对象,哪些对象占用了大部分内存并调查它们为什么以及由谁保存在内存中。

【讨论】:

【参考方案2】:

您应该限制同时运行的线程数量,也许您可​​以使用线程池,这样您就可以将添加的线程排队并超过您定义的池大小。

https://msdn.microsoft.com/en-us/library/h4732ks0.aspx

【讨论】:

以上是关于创建大量线程时.Net内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

。net应用程序在特定计算机中的内存泄漏

如何检测内存泄漏

libxml2.2.dylib 造成大量内存泄漏

发现 .NET 内存泄漏?

ios UIWebView中的大量内存泄漏

线程内存泄漏