0

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();
            }
    }
Max CHien
  • 133
  • 1
  • 8
  • 1
    What are you trying to achieve? Why are you calling `GC.Collect();`? – Irshad Dec 17 '15 at 07:21
  • Trying delete datatable and get memory immediately – Max CHien Dec 17 '15 at 07:24
  • The DataTable class dates from .NET 1.0, back when Microsoft wasn't thinking that clearly yet. It inherits from MarshalByValueComponent, an early framework design quirk. That gives it a finalizer, somewhat special in that it does nothing at all. Other than keep the memory occupied on the first GC.Collect() call. It requires two with a GC.WaitForPendingFinalizers() call in between. Another way to do it is to call dt.Dispose() first. Don't do this. – Hans Passant Dec 17 '15 at 08:42
  • Thanks Hans, is that means call gc.collect does not do anything? – Max CHien Dec 17 '15 at 10:07
  • And since DataTable is Unmanaged resource, so we have to call dispose(), but dispose in DataTable doesn't actually do anything useful in the finalization [dispose issue](http://stackoverflow.com/questions/913228/should-i-dispose-dataset-and-datatable) – Max CHien Dec 17 '15 at 10:10
  • update: try call `GC.Collect()` at new Thread, and it did Collect memory – Max CHien Dec 18 '15 at 09:26

1 Answers1

2

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.

René Vogt
  • 43,056
  • 14
  • 77
  • 99
  • thanks, one more question, why in vs2015 diagnosis tool,calling GC.Collect in click event did collect memory. – Max CHien Dec 17 '15 at 08:02
  • There are different operation modes in which a garbage collection can run. And the behaviour in debug mode is different again. I can't tell what exactly happens in your debugging scenario. – René Vogt Dec 17 '15 at 08:25
  • Thanks René Vogt, i use default scenario in visual studio 2015, – Max CHien Dec 17 '15 at 10:14
  • update: try call GC.Collect() at new Thread, and it did Collect memory – Max CHien Dec 18 '15 at 09:26
  • @MaxJ I still don't see why you want it to collect memory. It will collect if it decides it's necessary or time to. If you request memory and GC sees that it needs to clean up to free enough memory to answer your request, it will do it. Very smart people put a lot of effort into developing smart algorithms for that. There is no need to tell the GC what to do from user code. – René Vogt Dec 18 '15 at 09:28