0

VB.NET 2010, Framework 3.5

Trying to figure out how to get the memory back after I'm done with a list of a custom object type. I know forcing the list out of scope will reallocate the memory it's using but I need a way of doing it pragmatically. Does anyone know how to do this?

Public Class List_Of_T_Test
    Private MyTestClass As New List(Of TestClass)


Private Sub List_Of_T_Test_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    Const LIST_COUNT As Integer = 5000000
    Dim Count As Integer = 0

    MsgBox("Note 'PF usage' on Windows Task Manager 'before the 5m list' is created")

    Do Until Count > LIST_COUNT ' 5 million iterations 
        MyTestClass.Add(New TestClass With {.Value1 = CStr(Count), .Value2 = CStr(Count + 1)})
        Count = Count + 1
    Loop

    MsgBox("Note 'PF usage' on Windows Task Manager 'after the 5m list' was created")

    DestroyMyTestClassList()

    MsgBox("When flow arrives here, I need MyTestClass to be gone, all memory to have been reallocated, or close to where it was before the list was created")

End Sub

Private Sub DestroyMyTestClassList()

    ' Does anyone know what code to put here, code that would totally destroy 
    ' the MyTestClass and the 5 million items in it, reallocate the memory used 
    ' by the list Of(T) MyTestClass

    ' MyTestClass.Clear()   ' Doesn't work  ??
    ' MyTestClass = Nothing ' Doesn't work  ?

End Sub
Public Class TestClass

    Public Property Value1 As String
    Public Property Value2 As String

End Class

End Class

I understand the idea of letting it go out of scope but I have to tell you, I tried Disposing the form, closing it etc and loading a separate form and the memory still didn't come back. I guess GC hadn't got around to its collection business or something. I'll have to watch the GC work a bit longer I guess

This feller by the name of Jods was curious as to why I wanted to do this programmatically. The type of work I'm doing, creating copious types of custom lists that will be very dynamic in nature, that I need a way to destroy them and rebuild them with certainty that the old stuff is gone. These apps run non-stop for weeks sometimes so . . I need to pay close attention to memory and whatnot.

If of any interest to anyone, see code below that seems to reallocate the memory from a list of objects

Public Class List_Of_T_Test
Private MyTestClass As New List(Of TestClass)

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Const LIST_COUNT As Integer = 5000000
    Dim Count As Integer = 1

    Do Until Count > LIST_COUNT ' 5 million iterations 
        MyTestClass.Add(New TestClass With {.Value1 = CStr(Count), .Value2 = CStr(Count + 1)})
        Count = Count + 1
    Loop
    MsgBox(MyTestClass.Count.ToString)
End Sub

Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
    ' This seems to completely reallocate the memory, paste this into a form's code, 
    ' add two buttons, click button1 once, or few times while watching the 
    ' 'Windows Task Manager' PF Usage.

    ' Then Click button2 once and the memory spike levels off, it all comes back

    MyTestClass = New List(Of TestClass)
    GC.Collect()  ' ?
End Sub

Private Class TestClass

    Public Property Value1 As String
    Public Property Value2 As String

End Class

End Class
Rose
  • 641
  • 7
  • 17
  • 2
    Simply make it a local variable of your method instead of a class member. Neither Windows nor the garbage collector have the behavior you are looking for, intentionally releasing resources when it isn't necessary is too expensive. – Hans Passant Jul 22 '13 at 17:53
  • I've been beating on this pretty hard since yesterday.. The two lines, they appear to work very well, the memory seems to be reallocated instantly. 'MyTestClass = New List(Of TestClass)' and 'GC.Collect()' Do you or anyone else see a problem with this approach? – Rose Jul 23 '13 at 15:47

2 Answers2

2

I'm very curious why you need a way to do it programatically. When your objects are not used anymore (all references are un-reachable / out of scope / or set to null), the memory is reclaimed by the next run of the garbage collector.

If you want to trigger a collection by code you should call GC.Collect(). If you have finalizers you might have to call GC.WaitForPendingFinalizers() and then GC.Collect() again.

Note that calling these methods is generally frown upon, so I'm curious about your case.

jods
  • 4,581
  • 16
  • 20
  • 1
    Also note that GC.Collect() is a request, and not guaranteed to execute. http://msdn.microsoft.com/en-us/library/xe0c2357.aspx – ginman Jul 22 '13 at 18:35
  • @ginman I remember discussing this once but the details have eluded me. I recall that it was more a theoretical consideration than a practical one. BTW, your MSDN link says: "Forces an immediate garbage collection of all generations." with no mention of a possible non-execution of the GC. – jods Jul 23 '13 at 13:05
  • Yeah, that is misleading. Further down it notes: "Use this method to try to reclaim all memory that is inaccessible." What it does is force the GC Collection thread to run, which does not guarantee collection. See this issue where GC.Collect does not reclaim memory as expected - http://stackoverflow.com/questions/888280/garbage-collection-does-not-reduce-current-memory-usage-in-release-mode-why – ginman Jul 23 '13 at 20:56
-1

When the .NET framework instantiates an object, it allocates memory for that object on the managed heap. The object remains on the heap until it's no longer referenced by any active code, at which point the memory it's using is "garbage," ready for memory deallocation by the .NET Garbage Collector (GC). Before the GC deallocates the memory, the framework calls the object's Finalize() method, but developers are responsible for calling the Dispose() method.

So, just call the Dispose() method of your object(s).

Abbas Amiri
  • 3,074
  • 1
  • 23
  • 23
  • 2
    This makes no sense. Dispose doesn't have anything to do with memory and the List<> class doesn't implement it. – Hans Passant Jul 22 '13 at 17:58
  • Dispose is for releasing **unmanaged resources**. If a list does not have any references to it, it will be release by the garbabe collector when appropriate. – Abbas Amiri Jul 22 '13 at 18:15