gpt4 book ai didi

c# - 为什么即使在强制垃圾回收时,已完成的线程使用的内存也不会被释放?

转载 作者:行者123 更新时间:2023-12-03 21:52:09 27 4
gpt4 key购买 nike

我有一个 C# WinForms 应用程序,其中按下一个按钮实例化一个对象,订阅它的事件,然后基于该对象的方法启动一个线程。该对象的方法使用大量内存,但一旦线程完成,我认为应该在调用 GC.Collect() 时释放它。然而,情况似乎并非如此。该程序最多可以使用 GB 的内存,所以这不是一个小问题,它似乎只有在关闭程序或再次按下按钮时才会被释放。

这是一个演示问题的示例应用程序:

using System;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private Worker worker;

private void button1_Click(object sender, EventArgs e)
{
worker = new Worker();
worker.Finished += worker_Finished;

Thread thread = new Thread(new ThreadStart(worker.DoWork));
thread.IsBackground = true;
thread.Start();
}

void worker_Finished(object sender, EventArgs e)
{
worker.Finished -= worker_Finished;
GC.Collect();
MessageBox.Show((Environment.WorkingSet / 1024 / 1024).ToString() + " MB in use");
}
}

public class Worker
{
public event EventHandler Finished;
protected virtual void OnFinished(EventArgs e)
{
EventHandler handler = Finished;
if(handler != null)
{
handler(this, e);
}
}

public void DoWork()
{
Random random = new Random();
string[] list = new string[10000000];
for(int i = 0; i < list.Length; i++)
{
list[i] = random.NextDouble().ToString();
}
//list = null;
OnFinished(new EventArgs());
}
}
}

请注意,在这种情况下,取消注释行 list = null; 似乎可以解决问题,但我不确定为什么。在我的实际应用程序中,我曾尝试在函数结束前将所有大对象设置为 null,但似乎无济于事。所以这不是问题的完美重现,但希望有人可以解释这里发生的事情,这将帮助我解决实际问题。

此外,我知道 this question非常相似,但在我的例子中,我明确地强制进行垃圾回收。

最佳答案

垃圾收集是一件复杂的事情。这不仅仅是回收所有使用的内存的情况。对象之间存在复杂的关系需要考虑,因此 GC 必须确保它不会清理仍然可以在某处访问的对象。

因为您在 DoWork 方法完成之前引发事件,“list”变量仍在范围内,所以当您调用 Collect 时无法清除其内容。通过将变量设置为 null,您删除了对数组的引用,因此删除了它引用的所有 String 对象,因此可以通过调用 Collect 回收它们的所有内存。

关于c# - 为什么即使在强制垃圾回收时,已完成的线程使用的内存也不会被释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21470936/

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