• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1031
  • Last Modified:

Proper way to dispose dynamically created controls.

Hi,

I have adopted a technique in VB.NET that allows me to design a group control with several children controls as a template that can be cloned as needed. I instantiate the template form that holds the group control, then insert the group control into my application's form. This is leaking memory and I do not know how to get rid of the leak. What is the proper way to dispose of the template form and group control?
I have included a simplified sample of what the source code looks like.

Public Class MainForm
    Private templateObject as object
     Public Sub CreateNewGroupBoxTemplate()
           Dim tempTemplateForm as new FTemplateForm
           templateObject = tempTemplateForm.grpTemplateGroupControl
           me.controls.add(templateObject )
           tempTemplateForm .Dispose()
     End sub

     Public Sub DeleteTemplate()
          me.controls.remove(templateObject )
          templateObject.Dipose()
     End Sub
End Class
0
aferia
Asked:
aferia
  • 2
  • 2
  • 2
  • +1
3 Solutions
 
Daniel Van Der WerkenIndependent ConsultantCommented:
You should only be *implementing* and also calling Dispose if you are using unmanaged resources. I don't think you are doing that here.

http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.90).aspx

However, Garbage Collection (http://msdn.microsoft.com/en-us/library/0xy59wtx(v=vs.90).aspx) is the general term for what you want to do. And...it's best to let the system perform its own garbage collection. You could possibly induce the collection by calling GC.Collect() (rather than that Dispose() you have in your code), but again, it's best to let the system do that for you.

Try using GC.Collect() and see what happens.
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
More often than not, "leaking memory" is not actually occurring.  Usually it's just .Net being greedy and not immediately releasing memory since it may need it again in the near future.  The garbage collector runs at an indeterminate time so that memory will be released eventually, or if the system feels "pinched" and decides it needs to release it sooner rather than later, then it will.  Long story, short, if you don't have any un-managed resources as Dan7el mentions, and you don't have any other references to those controls elsewhere, then you just need to trust that .Net knows what it's doing...
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
*There is a difference, though, between trusting .Net and using an inefficient design.  We can't tell from your posted code if you are doing something in a way that might be better achieved with a different approach...  ;)
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
käµfm³d 👽Commented:
This I agree with:

You should only be *implementing* ... Dispose if you are using unmanaged resources

...this I do not:

You should only be ... calling Dispose if you are using unmanaged resources

Open in new window


If an item has a Dispose method available, then it probably does so for a reason. I think the calling of Dispose above is appropriate assuming the code above is adding objects which inherit from the Control class--which does use unmanaged resources (e.g. window handles).

This I'm not sure I 100% agree with, but I kind of understand the intent:

Usually it's just .Net being greedy and not immediately releasing memory since it may need it again in the near future.

Memory isn't released by .NET immediately because garbage collection is an expensive operation. For this reason I strongly discourage the use of GC.Collect. It is very rare that you would ever need to call this method, and if you put this call in the wrong place in your code (i.e. a place called frequently), you can assuredly bring your application to a halt.
0
 
Daniel Van Der WerkenIndependent ConsultantCommented:
I stand corrected. If a Dispose is there, you should call it or use the object in a using statement which automatically calls Dispose. I was really thinking that it should be implemented in an object that uses unmanged code and called accordingly.
0
 
aferiaAuthor Commented:
Thanks everyone!
From what I understand a container control should dispose all of its children when all reference variables for that control fall out of scope or are set to nothing. Does .NET's GC check all the reference variables in my program to determine what needs to be deallocated? Doesn't the GC call Dispose on the variables that have lost all references? So in theory, shouldn't I see the memory footprint going down if I am 100% sure that I have removed all references to a control and called GC.Collect() (even without calling dispose)?
Also, manually calling dispose(), but not clearing out the reference to nothing (assuming that it will stay in scope) seems to have no effect on the memory allocation.
I have researched the subject on Google, but I have not been able to find a  single comprehensive source on precisely how to answer these questions, please help!
0
 
käµfm³d 👽Commented:
Doesn't the GC call Dispose on the variables that have lost all references?
No. Dispose is the programmer's job; Finalize, IIRC, is the GC's job. However, I believe if you properly implement the Dispose pattern, then the finalizer will attempt to call the Dispose method. The Dispose method should succeed even if the method was previously called (i.e. calling Dispose on the same object twice should not raise an exception).

Does .NET's GC check all the reference variables in my program to determine what needs to be deallocated?
Yes, that is the whole idea behind garbage collection. But the GC deallocates managed objects. The reason we have Dispose and Finalize is to release unmanaged resources--things which the GC can neither see nor touch. It is your responsibility to ensure that such resources are released back to the system in a safe manner.

Also, manually calling dispose(), but not clearing out the reference to nothing (assuming that it will stay in scope) seems to have no effect on the memory allocation.
The old VB6-style of setting variables to Nothing is no longer needed in .NET. If there are no references to an object, it will be garbage collected. As Idle_Mind stated:  you have no way of knowing when. (OK, I think there might be a way--I seem to recall reading--but it ain't pretty. That's a very vague memory, so don't quote me on it!) Setting a local variable to Nothing will invalidate the reference so that it no longer points to the object in memory, but so will a variable leaving scope.

I have researched the subject on Google, but I have not been able to find a  single comprehensive source on precisely how to answer these questions, please help!
You'll probably want to invest in a book on the CLR. I don't know if you've read the following, but they might give you a better understanding:

http://msdn.microsoft.com/en-us/magazine/bb985011.aspx
http://msdn.microsoft.com/en-us/magazine/bb985010.aspx
http://msdn.microsoft.com/en-us/library/ms973837.aspx
0
 
aferiaAuthor Commented:
Thank you very much for your help! I wish I has more points to distribute!
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 2
  • 2
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now