meera123

Hi,
Please find below a sample application which demonstrates the above problem.If we run this code from memory profiler we can see that List object live count is 1 even we close Form1.
//This is my Test form code
namespace ListTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
List<InfoClass> infoList = new List<InfoClass>();
//ArrayList infoList = new ArrayList();
InfoClass info1 = new InfoClass();
info1.Name = "John";
info1.Id = 1;
infoList.Add(info1);
InfoClass info2 = new InfoClass();
info2.Name = "John";
info2.Id = 1;
infoList.Add(info2);
ultraGrid1.DataSource = infoList;

}
}
}

//This is the infoclass code.Here i added IDisposible also but still the problem persists.

namespace ListTest
{
class InfoClass :IDisposable
{
private string _name = string.Empty;
private int _id = 0;

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{

}

~InfoClass()
{
// Simply call Dispose(false).
Dispose (false);
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}

public int Id
{
get
{
return _id;
}
set
{
_id = value;
}
}
}
}

Now from a mainform i am calling
Form1 form = new Form1();
form.Show();
So when i close Form1 ,with mainform(MDIParent still open) in memory profiler still i see the live count of infoClass[] as 1.
Here is the memory profiler results.

Namespace Name Total(Live instances) New(Live instances)
ListTest Form1 0 0 0 0 0 0 0 0 0.04 14.3
ListTest InfoClass 0 0 0 0 0 0 0 0 0.09 1.4
ListTest InfoClass[] 1 1 0 1 16 16 16 16 0.09 2.1
ListTest MDIParent 1 1 0 1 540 540 540 540 0.04 23.5

Please help me to fix this problem


Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

John Willemse

> Now from a mainform i am calling
> Form1 form = new Form1();
> form.Show();
> So when i close Form1 ,with mainform(MDIParent still open) in memory profiler still i see the live count of infoClass[] as 1.
> Here is the memory profiler results.

You didn't show how you close the Form1 form. Do you call Dispose() or Close()





Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

meera123

Hi,
I am clicking Form1 Close button on the UI and also added the following code for handling Form_Closing() event.

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//System.Collections.Generic.List<InfoClass> infoList = (dataGridView1.DataSource as System.Collections.Generic.List<InfoClass>);
//dataGridView1.DataSource = null;
//dataGridView1.Dispose();


//foreach (InfoClass inf in infoList)
//{
// inf.Dispose();
//}

//for (int i = 0; i < infoList.Count; i++)
//{
// infoList.Pop(infoListIdea);
//}
//infoList.Clear();
//infoList = null;
this.Dispose();
GC.Collect();
}

But again the above results from memory profiler.




Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

Mattias Sjogren

List<T> doesn't implement IDisposable so it can't be disposed. But the object should still be eligible for garbage collection and cleaned up the next time a GC occurs.






Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

MatteoSp

As Mattias said, List<T> is not disposable. Neither should be disposable your InfoClass as it does not use unmanaged resources. The only reason (for the code I can see) for seeing 1 as live count is ultraGrid1, which use your list as datasource. Is it a DataGridView What about the live count of this type





Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

nobugz

You are calling GC.Collect() too soon to be able to collect your InfoClass[] object. It is being kept alive because of the reference held by the Form object. The Form object is still very much alive by the time the FormClosing event runs. Which keeps the object alive too. You might have noticed that a Form object never gets collected, even though there is no active reference to it anywhere. The Form object is being kept alive by an internal handle-to-object mapping table inside Windows Forms. It keeps the form from suddenly blinking out of existence when the next GC collection runs.

The reference to the form (and by inference, your InfoClass) doesn't disappear from the mapping table until WF gets the WM_NCDESTROY message, the message that Windows sends just before it makes the Handle invalid. Although it might technically possible to wire into that message to call GC.Collect(), there is absolutely no reason to do so. The trusty garbage collector will finish your object off when it decides the time is right. It is almost never wrong, certainly not in this case.

Next time you try to diagnose a memory leak problem, be sure to create and destroy (dispose) an object no less than 100 times. If the memory usage keeps going up, and increases well beyond 2 megabytes, you might have a real leak.





Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

meera123

Hi Mattias,
Yes.I have tried with both the Grids.One with Infragistics ultragrid as well as DataGridView.In both cases the live count of
both are zero and even the form1 is zero once the form is closed.But only InfoClass[] live count is always one.
Why is this happening How do we resolve this




Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

meera123

Hi,
I found this infoClass[] instance remains till the life time of the application and never get garbage collected.So how do we do it.




Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

meera123

Hi,
One more thing.If instead of infoClass if i hold a custom Structure inside the List , then also that customstruct[] instance remains with live count 1 on closing the form eventhough that array is not binded to any grid.For example here is the code.
private void Form1_Load(object sender, EventArgs e)
{
List<customStruct> structList = new List<customStruct>();

//ArrayList structList = new ArrayList();
customStruct struct1 = new customStruct();
struct1.Name = "Jins";
struct1.ID = 1;
customStruct struct2 = new customStruct();
struct1.Name = "Jancy";
struct1.ID = 2;
structList.Add(struct1);
structList.Add(struct2);
}

struct customStruct
{
private string name;
private int id;

public string Name
{
get
{
return name;
}
set
{
name = value;
}
}

public int ID
{
get
{
return id;
}
set
{
id = value;
}
}
This is the almost similar code except that instead of InfoClass, customStruct is added to List.
Now on closing the Form1 ,
Here is the Memory Profiler results.
Namespace Name Total(Live instances) New(Live instances) Removed(Live instances) Delta(Live instances) Total(Live instance sizes) Max(Live instance sizes) Min(Live instance sizes) Delta(Live instance sizes) Allocs/sec Bytes/sec
ListTest customStruct[] 1 1 0 1 12 12 12 12 0.12 3.3
ListTest Form1 0 0 0 0 0 0 0 0 0.06 19.5
ListTest MDIParent 1 1 0 1 540 540 540 540 0.06 32.2

We can see the customStruct[] count is 1.Form1 count is 0.
Here te List<T> is not binded.But still instance remains.How do we dispose it




Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

meera123

Hi nobugz,
So if that is case, do you mean to say , calling GC.Collect will not help in disposing this InfoClass[] object.In my actuall code most of our business class entities are returned in the form of InfoClass[] to the calling form.So even if we close all Forms which are calling the business classes, the correspoding BusinessInfoClass[] live count is always 1 even if all Form from which it is calling the business class is 0.So this leads to lot of live instance of each business class to remain in memory.I found that this remains in memory till the life time of the application.I feel this is a memory leak.Do you agree If i replace all List<T> with just ArrayList , no leaks at all.But for better performance we have used List<T>.
So is there anyway we can get all the live count of these InfoClass[] to 0.Please help.




Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

nobugz

As I tried to explain, the original timing of the GC.Collect() call was too early to have an effect. If you are now seeing an ArrayList getting collected but not a List<>, you should probably try a different profiler. Above all, repeat the test many times, you only have a leak if memory use climbs without bound.





Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

Peter Ritchie

What nobugz is saying is that because you're calling GC.Collect within the event handler of your Form object you Form object is therefore not disposed. If an object is not disposed all of it's members still have a reference and cannot be collected. You need to call GC.Collect after Form.Dispose is called (after using statement or after the call to Application.Run.)






Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

meera123

Hi,
Ok.I tried removing the GC.Collect code from Form1's event handler and added the same after Application.Run().
But again even after closing the Form1, i can see the instance of InfoClass[].
Now what would the problem.





Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

meera123

Hi,
Will this problem get solved if i make a List<T> disposable. Is there any way of making List<T> Disposable.How can i derive a class from List<T> or IList<T> where T is disposible.
Please give me some code samples.




Re: .NET Base Class Library List<T> collection not getting disposed even after closing the form.

nobugz

I seriously doubt that's your real issue. If InfoClass implements Dispose(), you should see a bunch of the InfoClass objects live, hanging in the finalizer queue waiting for the finalizer thread to become active and execute the finalizers. Can your profiler trace objects in that queue To be sure that the object doesn't linger in that queue, call GC.WaitForPendingFinalizers() after calling GC.Collect().

The notion of having a disposable object in a collection is not covered by any of the collection classes. It is not hard to make your own though:

using System;
using System.Collections.Generic;

public class DisposableList<T> : List<T>, IDisposable where T : IDisposable {
public void Dispose() {
foreach (T item in this) item.Dispose();
this.Clear(); // Optional: avoid chance of referencing disposed items
}
// NOTE: no need for a finalizer
}