Question get back memory with dispose

Zexor

Well-known member
Joined
Nov 28, 2008
Messages
520
Programming Experience
3-5
I have a program that creates controls in a flowlayoutpanel, and a button that clear all the controls. there are 2 sets of controls i add. One is label in a panel, the other is a picturebox and a progressbar in a groupbox. I did a test load of 20 of them, mostly the groupbox one with image. and it increase the memory by around 30Mb. Then i hit clear and it only get back around 10MB. I dont know what else to dispose.
I dispose the progressbar once its done loading. and when i hit clear, I dispose the image in the picbox, the picbox itself, then the groupbox. Also the label and panel. then i clear the flowavpanel.controls.clear()
 
Disposing has nothing directly to do with memory. Memory is NOT a resource that is released by disposing. When there are no more references to an object in managed code it becomes eligible for garbage collection and the system chooses when to run the garbage collector. If you have disposed an object then it can be cleaned up by the garbage collector first time around. If you haven't disposed an object then it gets finalised by the garbage collector the first time and then cleaned up next time. In reality it's more complex than that but that's the basics. You DO NOT need to worry about a few MB of memory. You dispose your objects when you're done with them and make sure there are no unnecessary references lying around and let the garbage collector look after the rest.

If you allocate a lot of memory and then finish with it but your app continues with some heavy processing then it might be necessary to invoke the garbage collector explicitly but such instances are very much the exception rather than the rule. Only do that if you actually have to because your app is running out of memory.
 
As jmcilhinney mentioned the garbage collector should clean up things if you've disposed the objects, but may not happen immediately. For testing purposes you could issue a
VB.NET:
GC.Collect()
to force garbage collection. You can also use a
VB.NET:
GC.GetTotalMemory(False)
to determine the number of bytes allocated before the garbage collection, then use
VB.NET:
GC.GetTotalMemory(True)
after you force the garbage collection. The boolean parameter here is specifying whether this method should wait for garbage collection to complete before returning.

Reiterating what jmcilhinney said, you would not normally want to force a garbage collection like this except for special cases. I am only suggesting this for testing so that you can see that the memory will be reclaimed by the garbage collector when it runs on its own after you have disposed your items.
 
So should i even dispose the controls and images? or just leave it to flowlayoutpanel.controls.clear
and for tabpage, just leave it to tabcontrol.remove(tabpage) for it to take care of all the controls in the page?
 
So should i even dispose the controls and images? or just leave it to flowlayoutpanel.controls.clear
and for tabpage, just leave it to tabcontrol.remove(tabpage) for it to take care of all the controls in the page?

The Clear method of the FlowLayoutPanel doesn't dispose anything. Nor does the TabControl.TabPages.Remove method. All they do is remove items from a collection. That's the equivalent of setting a variable to Nothing in that it removes the reference to the object and, if that's the last reference, makes the object eligible for garbage collection.

Any controls and components that you add to a form in the designer will be automatically disposed when the form is disposed. If a form is displayed by calling its Show method then its Close method will implicitly dispose it. If ShowDialog was called then you must dispose it explicitly. If you want to discard a control or component that was created in the designer before the form is closed then you should dispose that control or component explicitly.

Any time you create an object in code and that object has a Dispose method, it is your responsibility to dispose that object yourself in code when you're finished with it. If you create controls in code to add to a FlowLayoutPanel and you later want to remove them from the FLP because you're done with them, you must dispose them too. You can either dispose them first and then remove them or you can add them to some other list, remove them from the FLP, loop through the other list to dispose them and then clear the other list. If you create and remove TabPages at run time then it's your responsibility to dispose them when you're done with them.

Any short-lived disposable objects should be created with a using statement. That way, the object will be disposed implicitly at the End Using statement. That is how forms displayed using ShowDialog should generally be handled, e.g.
Using dialogue As New SomeForm 'object created here
    'When ShowDialog returns, the form will be closed but not disposed.
    dialogue.ShowDialog()
End Using 'object implicitly disposed here
 
What about a picturebox. If i dispose the picturebox, does it also dispose the image?

Also if i dispose a tabpage that is created in code. does it also dispose all the controls inside it? or do i need to dispose all of them individially?
 
Last edited:
What about a picturebox. If i dispose the picturebox, does it also dispose the image?
And what if you had the same Image displayed in two PictureBoxes?
Also if i dispose a tabpage that is created in code. does it also dispose all the controls inside it? or do i need to dispose all of them individially?
When you tried it for yourself, what happened? If you put a Button on one TabPage and dispose the TabPage, can you then put the Button on another TabPage? If so then it's obviously not disposed. It's time to start thinking for yourself first. If you want to know if something is the case then test it and see what happens.

As for disposing, the rules are very simple:

1. If you created in code, you have to dispose it when you're done with it.
2. If you didn't create it in code then you probably don't have to dispose it but there may still be instances where you do, so look carefully. E.g. the Graphics object created for a Paint event is not created by you and doesn't need to be disposed by you. On the other hand, a data reader returned by a data access library does need to be closed, which is equivalent to disposing, by you.
 
You DO NOT need to worry about a few MB of memory.

While I agree with everything else you said, this is very bad advice to give to a beginner. DO worry about every MB you can save, because eventually MB's become hundreds of MB's as you app scales forward. Learning to stay conservative with CPU and memory usage early on should in my opinion be a priority amongst others. Just don't get ill over it, if you just don't see a way to save any significant memory without spending 10 hours on it, just leave it be.

Practicing this makes it a non-issue, as you eventually naturally develop more efficient code.

As for the whole disposing issue, use USING...END USING blocks everywhere you can, it's provided by the IDisposable pattern for a reason.
 
Last edited:
While I agree with everything else you said, this is very bad advice to give to a beginner.
Only if it's misinterpreted. I didn't mean that it's OK to use memory that you don't need. What I meant was it's OK if your app is shown to be allocated memory that you're no longer using because the system will clean it up automatically in due course. For the very few apps that do need to invoke the GC explicitly, that need will show up during testing, assuming that testing is done properly.
 
Back
Top