Link to home
Start Free TrialLog in
Avatar of mnichols1202
mnichols1202

asked on

Garbage Collection In CollectionBase Classes

I'm having a huge problem.  I have created a CollectionBase class called Photos.

Photos is a collection of Class Photo. and holds (go figure) a photo and some information about the photo (name, size and such)

The photos are stored as Blob data in a SQL database and Photos has a load method that loads the collection from the DB.

Ok... as a test i tried this:
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim Photos As New colPhotos

        Dim icount As Integer
        For icount = 1 To 10
            Photos.Load()
            Me.Label1.Text = Photos.Count
            Photos.Clear
        Next icount
        Me.Label1.Text = "Done"
        Photos.Dispose()
    End Sub

Now when I run this I watch the windows task manager.  The first iteration uses up about 15mb of memory,  The problem is that each susequent iteration uses another 15mb of memory.

when the loop finishes i've got 150+ mb of memory used that will not be returned until i close the program. In this test case a single form.
Nothing i have tried will release the memory untill the program exits.... I even tried waiting an hour to see if GC would eventually release it.
Tried Early binding ..  LateBinding
I've even tried :
       System.GC.Collect()
        System.GC.WaitForPendingFinalizers()

Why is VB holding onto that memory. I'm not creating another instance of the object (at least I think I'm not)
Anyone know how to get VB to release the memory.
I have several of these classes in an app and I noticed over time the mem utilization going Up...Up..Up


Avatar of Göran Andersson
Göran Andersson
Flag of Sweden image

Are you using any classes that implements IDisposable, like Image? Then you have to make sure that you call the Dispose method when removing them. Otherwise they will be hard to garbage collect, and they may leak system resources like windows handles. If you don't call Dispose, the objects have to be finalised before they can be collected. The finalisation is executed in a background thread, so if you leave a lot of object undisposed, it will take quite a while before they are finalised and can be collected.

Other than that, it's normal for a .NET application to allocate memory and don't free it unless it's needed. If the system needs the memory back, the garbage collector will make a more thorough collection.

Forcing a garbage collection is not something that you normally would do. The garbage collector handles this best on it's own. Also, calling the Collect method doesn't guarantee that all collectable objects are collected. The garbage collector decides for itself what objects are efficent to collect at any given time.
Avatar of Autoeforms
Autoeforms

just curious have you minimized and restored your app.
the footprint is normally reduced doing this. if yours is not something is still holding on to the memory
good luck these problems are pup
greg
Avatar of mnichols1202

ASKER

GreenGhost:
You Say: "Other than that, it's normal for a .NET application to allocate memory and don't free it unless it's needed. If the system needs the memory back, the garbage collector will make a more thorough collection."

The problem is that a .net app running on a windows machine is not running in a vacume.  I've seen a .net collection run.up 2GB of memory when the machine only has 512mb of real RAM. Obvously memory is "needed' by the system. by this .net application is hanging on to 1.9gb of what is supposed to be released memory.
After further investigation it seems that the problem is in the CollectionBase Clas itself not relaeasing memory when the .Clear method is call on the list.

What about a byte array. would this have the same collectin problems as say an image object?





> the problem is in the CollectionBase Clas itself not relaeasing memory when the .Clear method is call on the list.

The Clear method is not supposed to release any memory, other than the objects that it is referencing (if it is a collection of reference types).

The Clear method sets all items to 0/null and sets Count to zero, but it doesn't change the Capacity of the collection. If you want the underlying array to be freed, you should set the Capacity to zero also.

> What about a byte array. would this have the same collectin problems as say an image object?

An array in itself is a managed object and doesn't need any disposing. (If it is an array of references to objects that are disposable, the objects themselves of course needs disposing.)
Checking back to see if you had any progress?
I did - I found out that for some reason you must use the ERASE function to get a byte array to release it's memory for garbage collection.  Anyone feel like commenting as to why it works that way?
You don't need to use Erase, setting the reference to Nothing does the exact same thing.

From MSDN Library:

"The Erase statement is equivalent to assigning Nothing to each array variable."

I tried this, and the statement

Erase a

actually compiles into the exact same code as:

a = Nothing


An object is available for garbage collection when it can not be used any more. For member variables this is when the reference is set to Nothing (or when the parent object is available for garbage collection).
ASKER CERTIFIED SOLUTION
Avatar of Göran Andersson
Göran Andersson
Flag of Sweden image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial