gpt4 book ai didi

c# - 线程内存泄漏

转载 作者:太空狗 更新时间:2023-10-29 18:24:54 28 4
gpt4 key购买 nike

我正在尝试追踪生成多个线程的较大 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”。观察您的进程的句柄数量是如何稳步增加的。内存使用率随之上升,反射(reflect)了句柄对象使用的非托管内存。

设计选择非常大胆,CLR 每个线程使用 5 个操作系统对象。管道,用于同步。这些对象本身是一次性的,设计选择是让 Thread 类实现 IDisposable。这对 .NET 程序员来说是相当困难的,很难在正确的时间进行 Dispose() 调用。在 Task 类设计中没有表现出勇气,顺便说一句,导致很多人绞尽脑汁和 general advice not to bother .

在设计良好的 .NET 程序中,这通常不是问题。 GC 运行频率足以清理这些操作系统对象的地方。并且 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。

关于c# - 线程内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25677438/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com