Results 1 to 14 of 14

Thread: VB.Net form garbage collection behavior

  1. #1

    Thread Starter
    New Member
    Join Date
    Jan 2011
    Posts
    3

    VB.Net form garbage collection behavior

    I'm creating a windows forms program and have recently noticed a large amount of memory slowly being eaten by the application. I went through my program and tried to tie up as many loose ends as I could in relation to object creation but noticed that the program would still keep memory for every form loaded until it eventually crashed.

    I decided to make a simple test program which sole purpose is to pop-up a new form with a few controls, wait for 200 milliseconds, then close the form and repeat the process 30 times every time I hit a button. I found it caused the same behavior, even with the only new object creation being that of the form. So, I decided to manually invoke the garbage collector in a subroutine which handles the formclosed event. During tests I would get some memory back occasionally, but not enough to make a difference in the long run. So I start setting the form variable to nothing before I called GC.collect(). The program will initially eat a few 1000K of memory before leveling off and using only 20-40K for every 30 forms created.

    Now what I'm wondering is, what is the point of an automated garbage collection system if it requires constant manual evocation and explicit dereferencing of all new objects to be effective? Have I completely lost grasp on the scope of VB.Net forms and it simply never marks forms as available memory to be cleared? I would have thought object memory references created within a form would be marked as usable when the form's close or dispose routine is called and no references to objects created within the form exist anywhere outside the closed form.

  2. #2
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: VB.Net form garbage collection behavior

    Garbage Collection is expensive and isn't done immediately. If you have no references to the form, then there's no need to go around manually invoking Garbage Collection. Put bluntly: the Garbage Collection mechanism is a lot smarter than you are.

    Now all that remains is for your code to play fair and not hold references to things that aren't necessary to hold on to. VB has a Forms collection doesn't it? I wonder if this is holding references to forms that you create? Are you calling Close() on the forms or simply Hide()? I would expect if you called Close() then VB should play nicely and release any hidden references to the form as well.

    Can you post the code of the program you used to test this?

  3. #3
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687

    Re: VB.Net form garbage collection behavior

    Stack/Heap allocation takes time. So when you create an instance of a form, space is allocated for it... when you're done with the form, close it, dispose it and set it to nothing. The memory is still allocated for your application. If then invoke a new instance of the form, it *should* re-allocate the same space for it, re using the same memory space. But that only happens if it's the same form and the previous one was properly cleared/removed/disposed/whatever. And the new object can fit in the same footprint. That's the theory. I've seen it happen that way, as well as not...

    Based on a strict reading of your post, I'd say the step you missed was to dispose your forms ... which is NOT the same as setting it to nothing. Would you mind sharing the code you used to check this out?

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: VB.Net form garbage collection behavior

    You stated that the program would crash. Is that the endpoint you reached during your testing, or just in the actual program you were working on? Seeing the memory appear to expand is not all that surprising on its own, after all, the OS could manage things that way. However, if the result was a crash, then we can pretty well rule out this being a mirage caused by OS memory management, and something is holding onto those form references such that the forms never get tagged for cleanup.
    My usual boring signature: Nothing

  5. #5

    Thread Starter
    New Member
    Join Date
    Jan 2011
    Posts
    3

    Re: VB.Net form garbage collection behavior

    I've ran a few more tests without manually trying to help the GC along and it seems that the amount of memory used before tapering off increases but it eventually does stop growing. Total memory usage is around 2-3000K more than if I were to manually evoke GC.collect().

    I'm sure I still have improper scopes within my initial program, though I still get memory increases on forms which do not access outside objects. Which reminds me I forgot to test whether or not the way I'm showing those forms is what's causing the scope problems.

    Does anyone know if it's a bad idea to load forms into panels? Closing is done by casting the panel's only control as a form and actually using the close command. The compiler doesn't take issue with this and I know in certain cases memory is being cleared for objects within the sub-forms such as DataGridViews. For all I know the fact that the form was part of a panel's control collection could be causing my issues.

  6. #6
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: VB.Net form garbage collection behavior

    If you're not removing the form from the panel collection then that would [edit: probably, depending on how the Panel was being got rid of] stop garbage collection from collecting the form. Can we see the code that is exhibiting the behaviour? Without that, it's just guessing.

  7. #7

    Thread Starter
    New Member
    Join Date
    Jan 2011
    Posts
    3

    Re: VB.Net form garbage collection behavior

    I just ran another simple test, and yeah, this is starting to look more like I just need to go through the initial program with a fine tooth comb again to figure out where I've managed to keep my forms from being marked for garbage collection.

    The simple example I was talking about as far as closing the form using casting:

    subForm = New Form2
    subForm.TopLevel = False
    Panel1.Controls.Add(subForm)
    subForm.Show()
    Threading.Thread.Sleep(100)
    CType(Panel1.Controls.Item(0), Form).Close()

    500 runthroughs later and garbage collection is indeed doing its job so it's not a control collection issue.

    If anyone knows of any obscure ways of screwing up the scope of VB forms for me to look for I'd love to hear it.

  8. #8
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: VB.Net form garbage collection behavior

    From your last couple posts, it sounds like you are just seeing large memory usage without getting any actual crashes. This could easily be caused by a trade-off being made by the program. While allocating new memory is expensive, collecting the garbage is even more so. Therefore, it is entirely reasonable for a program to ask the OS for more memory rather than taking out the garbage. If the OS has plenty, then it might just give the app more and more, so the OS would be stockpiling memory filled with junk. Only when the GC runs will it recover any of that memory, but that doesn't mean that it will release the memory back to the OS. That would be inefficient from the perspective of the app. After all, it DID use that memory at one point, so it MIGHT need to again.

    By the way, closing a form that was shown nonmodally (with Show rather than ShowDialog) behaves considerably differently than closing a form that was shown modally. I believe that closing a modal form will call dispose on it, but closing a nonmodal will not.

    Aside from that, your code is holding all those forms forever. Every time through your code, you create a new form, add it to the collection (the collection holds that reference), then show form 0 (control 0, but it is a form). That is always the same form you are showing, though every time through the loop you are creating a new form and adding it to the collection...you just are never showing that new form you created, always the first one you created. Had you been showing it modally, you might have disposed of that first form when you closed it, which would mean that control(0).Show might have crashed with a Null reference exception, but since you were showing nonmodally, showing the same form again is no problem.
    My usual boring signature: Nothing

  9. #9
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: VB.Net form garbage collection behavior

    Quote Originally Posted by Shaggy Hiker View Post
    I believe that closing a modal form will call dispose on it, but closing a nonmodal will not.
    It's the opposite, which is why you should use a Using block to create and display modal dialogues.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  10. #10
    VB For Fun Edgemeal's Avatar
    Join Date
    Sep 2006
    Location
    WindowFromPoint
    Posts
    4,255

    Re: VB.Net form garbage collection behavior

    Quote Originally Posted by jmcilhinney View Post
    It's the opposite, which is why you should use a Using block to create and display modal dialogues.
    Am I doing it the right way?... I don't call close or dispose.
    Code:
    'Main Form
    
    Using FrmInput As New FrmInputData
        
        If FrmInput.ShowDialog() = Windows.Forms.DialogResult.OK Then
            ChangesMade = True
        End If
    
    End Using
    Code:
    'Form FrmInputData
    
    Private Sub ButtonOK_Click(...
        ' do stuff    
        Me.DialogResult = Windows.Forms.DialogResult.OK
    End Sub

  11. #11
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: VB.Net form garbage collection behavior

    Quote Originally Posted by Edgemeal View Post
    Am I doing it the right way?... I don't call close or dispose.
    That's what the Using block is for. The object created on the Using statement is disposed on the End using statement.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  12. #12
    VB For Fun Edgemeal's Avatar
    Join Date
    Sep 2006
    Location
    WindowFromPoint
    Posts
    4,255

    Re: VB.Net form garbage collection behavior

    Quote Originally Posted by jmcilhinney View Post
    That's what the Using block is for. The object created on the Using statement is disposed on the End using statement.
    Thanks jm, and sorry for stepping in on the OPs thread!

  13. #13
    PowerPoster
    Join Date
    Mar 2002
    Location
    UK
    Posts
    4,780

    Re: VB.Net form garbage collection behavior

    I found this tool great for tracking down leaks (there are others, I just have experience with this and it has a free 14 day trial!). Just start it up, point it at your .exe and run it for a couple of mins and take a snapshot. Do all those actions you think should be cleared up, so opening your forms multiple times, and then take another snapshot. You can then compare them and see the delta changes, it will show all instances still in memory AND most importantly, show you what is still referencing them.

    The memory leak that got me was using My.Resources. Each time you extract something, it will make a NEW copy of it, in my case I was switching between 2 icons passing into a 3rd party control. Memprofiler gave me the proof of where the issue was to give to the 3rd party to solve. (I love the old, "it must be you" general answer)

  14. #14
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: VB.Net form garbage collection behavior

    Quote Originally Posted by jmcilhinney View Post
    It's the opposite, which is why you should use a Using block to create and display modal dialogues.
    I know After I wrote that I realized I was getting modal and nonmodal backwards, but didn't fix all my mistakes.
    My usual boring signature: Nothing

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width