Max CHien
Max CHien

Reputation: 143

Data table dispose timing

In C#, I call GC.Collect() in both Form1_Load and click event

Question is GC.Collect() seems did nothing in Form_load

But works in click event. Why ?

GC.Collect() first time inForm1_Load

GC.Collect() second time inclick event

With visual studio 2015 diagnosis tool

 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();
            }
    }

Upvotes: 0

Views: 181

Answers (1)

Ren&#233; Vogt
Ren&#233; Vogt

Reputation: 43886

To call GC.Collect is the worst thing you can do (as in about 100% of the time).

GC.Collect checks the reference count of the objects in your application's memory. Since you set dt to null, there should be no more reference to that DataTable instance. Ok, so the garbage collection "collects" it. But that only means that it puts it on the finalizer queue. You did not call dt.Dispose which would have called GC.SuppressFinalize(this) to inform the gc that this object does not need to be put on the finalizer queue.

By enqueueing this object for finalization, there is a new reference to the DataTable and the object is moved up one generation. The result is that the garbage collection will keep this memory even longer.

By calling GC.Collect a second time in your button handler you make things even worse. Because again, all still referenced objects are moved up one generation and kept even longer.

You should simply dispose the DataTable by calling dt.Dispose or enclosing it in a using statement:

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
    }
}

And even if you do that, please don't call GC.Collect. Let the garbage collection do it's job as it always knows best how to do it. It will free unused memory if it needs to.

See Understanding Garbage Collection in .NET or this Microsoft article for further information.

Upvotes: 2

Related Questions