【发布时间】:2016-02-24 03:08:02
【问题描述】:
我正在学习更多关于线程的知识,并使用以下代码创建了一个相当简单的 WPF 应用程序(x64 平台构建)
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
for (var i = 0; i <= 20000; i++)
{
Thread thread = new Thread(Test);
thread.IsBackground = true;
thread.Start();
}
}
public void Test()
{
Thread.Sleep(20000);
}
}
当我运行此代码时,进程在所有线程都在运行/休眠时占用大约 560MB 的 RAM。
完成后,进程使用率降至大约 125 MB 的 RAM。
我的问题是,当应用程序本身(没有线程示例)仅使用 30 MB 的 RAM 时,为什么此时进程使用 125 MB 的 RAM?
它是否使某些线程保持活动状态以供可能的重用/使用或发生其他事情?
编辑:
由于对如何改进此代码的一些建议,我想指出,我不是在寻求改进它的方法,而是要查明这种行为的原因。
编辑 2:
这与线程无关,但我尝试了一个在内存中有一个大的string 列表的案例,但它没有产生相同的结果。当 list 完全加载到内存中时,大约需要 1.3 GB 的内存,但在 list 设置为 NULL 并调用 GC.Collect() 后,内存使用率按预期下降到 30 MB。
代码:
public partial class MainWindow : Window
{
List<string> stringArray = new List<string>();
public MainWindow()
{
InitializeComponent();
for (var i = 0; i <= 100000000; i++)
{
//Thread thread = new Thread(Test);
//thread.IsBackground = false;
//thread.Start();
stringArray.Add("Some very long string to pump up the memory volume 2 reloaded");
}
stringArray = null;
GC.Collect();
}
}
【问题讨论】:
-
当线程终止时,线程对象在未来某个不确定的时间点有资格进行垃圾回收。
-
对于初学者来说,每个线程都分配了一个默认的 1MB 堆栈,因此您在那里添加了大约 200MB。
-
@Aron 如果每个线程都被外部的东西阻塞,那么有很多线程是有原因的......
-
还有一种可能性。当 .net 分配内存(这很昂贵)时,即使在它被释放后,.net 也可能不会释放它,因此您可能会看到 125 mb。正如我所说,请转储,并使用 windbg 进行分析。该检查还将揭示我认为接近 95 MB 的空闲内存量(可供托管堆和堆栈使用)
-
20k 个对象不算什么,即使涉及最终确定,这也将占用接近零的内存。当线程完成时,线程堆栈被释放。线程退出时堆栈不会保持活动状态。为什么会呢?这个问题是有效的。到目前为止,有很多评论和支持的 cmets,但没有人在寻找答案方面取得任何进展。
标签: c# multithreading