Reputation: 41
I would like to ask what is the efficiency way the clean and dispose the object collected in the List (Of Object)?
Is that by calling the List.Clear() method will automatic clean all the object collected by it?
For Example consider the below example
public partial class Form1 : Form
{
FontCollection m_fontCollection;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
m_fontCollection = new FontCollection();
for (int i = 0; i < 5000; i++)
{
Font font = new Font("Arial", 23);
FontImpl impl = new FontImpl(font, Color.Black);
impl.AfterChange +=
new FontImpl.AfterChangeHandler(impl_AfterChange);
m_fontCollection.Add(impl);
}
m_fontCollection.Dispose();
MessageBox.Show("TakeSnap");
}
void impl_AfterChange()
{
throw new NotImplementedException();
}
}
public class FontCollection : IEnumerable, IDisposable
{
IList<FontImpl> m_Implementation = new List<FontImpl>();
internal void Add(FontImpl impl)
{
this.m_Implementation.Add(impl);
}
public IEnumerator GetEnumerator()
{
return this.m_Implementation.GetEnumerator();
}
public void Dispose()
{
m_Implementation.Clear();
m_Implementation = null;
}
}
public class FontImpl
{
private Font m_Font;
private Color m_color;
public FontImpl(Font newFont, Color newColcor)
{
m_Font = newFont;
m_color = newColcor;
}
public event AfterChangeHandler AfterChange;
public delegate void AfterChangeHandler();
}
When i run the above application ANTS memory profiler i could see the memory leaks Font and FontFamily (I could not able to upload the screen) and how to remove these leaks
Upvotes: 2
Views: 9286
Reputation: 17438
In the case of the code you have shown you have Font
objects which implement IDisposable
and thus should be disposed. Those objects are being managed by your FontImpl
class and so FontImpl
should implement IDisposable
. Your FontCollection
class contains a list of FontImpl
objects which should now be disposable and so FontCollection
needs to implement IDisposable
.
You should read up on the IDisposable pattern (this SO answer gives some great information - https://stackoverflow.com/a/538238/416574).
That being said, from the code snippet you provided it does not appear that you gain anything from your FontCollection
other than a class to wrap a list. Unless there are other things you are going to do with that class I would just have a list as a member variable. That way in the Dispose
method of your form you can walk your list and dispose the FontImpl
objects. If you want to protect from double disposing, then just empty the list after disposing everything.
Upvotes: 0
Reputation: 3503
Clear just removes everything from the list. In your case you have a list of IDisposable objects and you need to call Dispose on all the items in the list. Calling Clear does not do that.
Your FontImpl should implement IDisposable since it manages an IDisposable object:
public void Dispose() {
if (m_Font != null) {
m_Font.Dispose();
m_Font = null;
}
}
And your FontCollection Dispose should look like this:
public void Dispose()
{
foreach(FontImpl font in m_Implementation) {
font.Dispose();
}
m_Implementation.Clear();
m_Implementation = null;
}
Upvotes: 0
Reputation: 137467
In general, you shouldn't need to worry about garbage collection, and when it occurs. An object is eligible for GC when there are zero references to it.
The thing you should pay attention to, however, are IDisposable
objects. When you are finished with an IDisposable
object, you really need to be calling Dispose()
on it. If the object lives within the local scope of a functinon, then a using
block makes this easy:
using (var resource = new SomeIDisposable()) {
// use resource
// resource.Dispose() is automatically called, *even if* an exception
// is thrown.
}
You can cause memory leaks by ending up with "dangling references" to objects, which prevent them from being garbage collected. Most often the cause of this is with event handlers. When you subscribe to an event exposed by object A
, with an event handler on object B
, A
gets a reference to B
:
class B {
void hook_up_to(A a) {
a.SomeEvent += Handler; // `a` gets a reference to `this`
}
void Handler(object sender, EventArgs e) {
}
}
class Program {
private A _a = new A();
static void SomeMethod() {
var b = new B();
b.hook_up_to(_a); // _a now has a reference to b
// b goes out of scope.
}
}
Normally, when b
goes out of scope, the object it references would be eligible for garbage collection. In this case though, b
hooked up to an event published by member variable _a
, which caused _a
to gain a reference to b
. Now there is one outstanding reference to b
, which is impossible1 to clear, and b
is ineligible for GC. This is a memory leak.
1 The only way reference to b
in this case is this
pointer if/when the event handler is fired.
Upvotes: 3
Reputation: 102783
You don't need to implement IDisposable
on your class. In general the only time your class needs to implement IDisposable
is when it contains other classes that need to be disposed of (things like database and network connections, and unmanaged objects).
In your example, you might want to consider making m_fontCollection
a local variable within button1_Click
, since you're creating and disposing of it entirely within that method. If you make it local, then it will be garbage-collected once button1_Click
exits ... provided there are no remaining references to it (which indeed there are not in this case).
Upvotes: 1