数据表释放计时

本文关键字:释放 数据表 | 更新日期: 2023-09-27 18:27:04

在 C# 中,我在Form1_Load和单击事件中都调用GC.Collect()

问题是GC.Collect()似乎什么也没做Form_load

但在点击事件中工作。为什么?

GC.Collect() Form1_Load第一次

GC.Collect()第二次click event

使用视觉工作室 2015 诊断工具

 public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            DataTable dt;
            private void Form1_Load(object sender, EventArgs e)
            {
                dt = new DataTable();
                dt.Columns.Add("1", typeof(int));
                dt.Columns.Add("2", typeof(int));
                dt.Columns.Add("3", typeof(int));
                for (int i = 0; i < 1000000; i++)
                {
                    DataRow dr = dt.NewRow();
                    dr[0] = 10;
                    dr[1] = 1000;
                    dr[2] = 10000;
                    dt.Rows.Add(dr);
                }
                //gc first time 
                dt = null;
                GC.Collect();
            }
            private void button1_Click(object sender, EventArgs e)
            {
                //gc sec time 
                dt = null;
                GC.Collect();
            }
    }

数据表释放计时

打电话给GC.Collect是你能做的最糟糕的事情(大约 100% 的时间(。

GC.Collect检查应用程序内存中对象的引用计数。由于将dt设置为 null,因此不应再引用该DataTable实例。好的,所以垃圾回收"收集"它。但这仅意味着它将其放在终结器队列中。您没有调用dt.Dispose这会调用GC.SuppressFinalize(this)来通知 gc 不需要将此对象放入终结器队列。

通过将此对象排队等待完成,将有一个新的DataTable引用,并且该对象将向上移动一代。结果是垃圾回收将保留此内存更长时间。

通过在按钮处理程序中第二次调用GC.Collect,会使事情变得更糟。因为同样,所有仍然引用的对象都会向上移动一代并保留更长时间。

您只需通过调用dt.Dispose或将其括在 using 语句中来释放DataTable

private void Form1_Load(object sender, EventArgs e)
{
    using (DataTable dt = new DataTable())
    {
        dt.Columns.Add("1", typeof(int));
        dt.Columns.Add("2", typeof(int));
        dt.Columns.Add("3", typeof(int));
        //... your code
    }
}

即使你这样做,也请不要打电话给GC.Collect.让垃圾收集完成它的工作,因为它总是最知道如何做。如果需要,它将释放未使用的内存。

有关详细信息,请参阅了解 .NET 中的垃圾回收或此Microsoft文章。