.NET窗体关闭/处理不会取消分配全局对象

时间:2018-06-26 13:26:53

标签: c# .net winforms

编辑:请仅考虑我提供的示例。没有事件被调用。我提供的代码就是全部。我只想知道必须手动取消分配表单中的全局对象。也很高兴知道为什么不清除超出范围的表单,但这是次要的。

在窗体上关闭或调用处理似乎不会取消分配该窗体的全局对象。我有一个将被多次实例化的表单,并且在打开多次后,即使所有先前的表单都已关闭,我也会收到OutOfMemory异常。通过使我使用的每个对象都可以被释放,可以释放内存,但是我认为总的来说垃圾回收会清理超出范围的对象。

这是一个只有多维双精度数组的表单的简单示例:

using System;
using System.Windows.Forms;

namespace surGroupTool
{
    public partial class TestForm : Form
    {
        double[,] testArray;

        public TestForm()
        {
            InitializeComponent();

            testArray = new double[5000, 5000];
        }

    }
}

当我在无限循环中创建表单时,即使我将其丢弃并将其设置为null,它也会很快耗尽内存。

while (true)
{
    TestForm testForm = new TestForm();

    testForm.Dispose();
    testForm = null;
} 

是否必须以封闭/处置形式手动处置每个物体?

enter image description here

1 个答案:

答案 0 :(得分:-1)

enter image description here

我无法使用给定的源代码重现该问题。该屏幕截图的播放时间约为20秒。但是我在喝咖啡的时候让它运行,它仍然很好。如上所述,它正在循环存储模式。

我注意到的一件事是,GC释放内存需要一些时间。仅当开始内存不足或使用GC.Collect();手动调用GC时,GC才会运行。届时,将开始进行实际清洁的后台处理。此垃圾回收线程不会完全中断程序的主线程(根据Microsoft documentation>后台工作站垃圾回收)。因此,这意味着即使GC正在运行,也可以继续分配内存。那时是种族第一。您在分配足够的内存以超出范围。或您的GC及其清理。

  

是否必须以封闭/处置形式手动处置每个物体?

不,通常不必处置全球资源。如果没有引用它们,GC将清理它们。但是,如果全局资源是非托管资源(例如streambitmap),则需要先对其进行处置,然后才能对其进行清理,这与本地非托管资源相同。

来自评论:

  

即使每个表单都是由用户单击按钮创建的,也会在创建表单之间产生分钟的时间。

我将假设这是在您的实际应用程序中,而不是作为测试样本提供的表格。您最有可能留下对该表单的引用(例如,通过对话框结果或打开未损坏的资源)。如果使用给定的格式,我将无法解释它,您可能需要检查是否没有将GC设置覆盖为非常特殊的内容,或者是否将其全部禁用。