Results 1 to 9 of 9

Thread: Unbinding from a DataGridView, memory leak?

  1. #1

    Thread Starter
    Fanatic Member Andy_P's Avatar
    Join Date
    May 2005
    Location
    Dunstable, England
    Posts
    669

    Question Unbinding from a DataGridView, memory leak?

    Using VS Express 2008 and .NET2.0.

    I have a DataGridView which has as its .DataSource a BindingSource, which in turn has its .DataSource set to a BindingList<> which contains some classes.

    All works well, and I potentially have a list of several thousand items, and hence several thousand rows on the grid.

    When I wish to disconnect binding, clear the list and hence clear the grid, I am setting the grid DataSource property to Nothing, and calling .Clear in the BindingSource.

    However, it appears that when I do this, the memory usage (Private bytes) does not reduce until TWO full GC's occur. (Both metrics checked with PerfMon.)

    I can only surmise that the original row instances in the grid are hanging around and making it on to the Finalizer queue perhaps?

    Is there anything I can do about this, or is it expected behaviour? I'm not sure if setting the DataSource property to Nothing is enough to 'purge' the grid properly.

    Using Reflector, I notice that DataGridViewRow inherits Dispose from it's base class, so do I have to call this somehow, or should the act of unbinding do this automatically?

    (The classes in the list are purely managed, and have nothing that requires Dispose calling on them.)


    Thanks for any help.
    Using Windows XP Home sp3
    Mucking around with C# 2008 Express
    while ( this.deadHorse ) { flog( ); }


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

    Re: Unbinding from a DataGridView, memory leak?

    How are you creating the BindingList in the first place? Is there maybe an array or the like that also has a reference to the items? It sounds like those items are referenced somewhere other than the BindingList, otherwise I would expect them to be cleaned up on the first collection.
    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

  3. #3

    Thread Starter
    Fanatic Member Andy_P's Avatar
    Join Date
    May 2005
    Location
    Dunstable, England
    Posts
    669

    Re: Unbinding from a DataGridView, memory leak?

    Quote Originally Posted by jmcilhinney View Post
    ...I would expect them to be cleaned up on the first collection.
    This is what I expected too.


    I am using the BindingList as follows. (Please forgive the C# syntax...)

    Code:
    myClassList = new BindingList<MyClass>();
    bindingSource.DataSource = myClassList;
    dgv.DataSource = bindingSource;
    .
    .
    myClass = new MyClass();
    myClassList.Add(myClass);
    The instances of MyClass only get added to the list, they do not get added to an array, or individually referenced anywhere. (At least, not intentionally.)

    I guess I may have to make a test project to investigate further.
    Using Windows XP Home sp3
    Mucking around with C# 2008 Express
    while ( this.deadHorse ) { flog( ); }


  4. #4

    Thread Starter
    Fanatic Member Andy_P's Avatar
    Join Date
    May 2005
    Location
    Dunstable, England
    Posts
    669

    Re: Unbinding from a DataGridView, memory leak?

    Interestingly, if I bind a list that is already filled, and do not add to it, the memory is reclaimed correctly when the binding is removed, and the list is cleared.

    The problem occurs when I bind the list, and then periodically add to it. (This is what I would like to do, as I am logging data from a machine controller and I want to see the additions to the grid in real time.) The additions could be as frequent as ecery 500ms, but typically around one every second.

    It appears that in this case the rows are not being cleaned up properly when binding is removed.

    Not sure where to go from here? Any thoughts appreciated.
    Using Windows XP Home sp3
    Mucking around with C# 2008 Express
    while ( this.deadHorse ) { flog( ); }


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

    Re: Unbinding from a DataGridView, memory leak?

    If you're using a BindingList, is there really any need for a BindingSource? If you're not using the navigation methods then probably not. I wonder whether that would make a difference?
    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

  6. #6

    Thread Starter
    Fanatic Member Andy_P's Avatar
    Join Date
    May 2005
    Location
    Dunstable, England
    Posts
    669

    Re: Unbinding from a DataGridView, memory leak?

    Good suggestion, had not thought to try that, although it appears to exhibit the same behaviour.

    As a test, I am manually filling a BindingList and then binding it directly to the grid.

    The grid displays correctly, and after unbinding and clearing the BindingList, the memory is recalimed on the first full GC. (I put a button on the form to force a GC.Collect.)

    If however I bind an empty list to the grid first, and then fill it, the grid still displays correctly, (although it does take longer to display). When I unbind and the clear the list, I need to call GC.Collect twice before the memory is reclaimed. Hmmm.

    To clarify, the memory values I am checking are 'Private bytes' and 'Bytes in all heaps' and I am targetting .NET2.0 with sp2.
    Using Windows XP Home sp3
    Mucking around with C# 2008 Express
    while ( this.deadHorse ) { flog( ); }


  7. #7

    Thread Starter
    Fanatic Member Andy_P's Avatar
    Join Date
    May 2005
    Location
    Dunstable, England
    Posts
    669

    Re: Unbinding from a DataGridView, memory leak?

    Further tests indicate that additons to the list before binding it to the grid are reclaimed after one GC when binding is removed, while additions made to the list after databinding take two GC's when unbound.

    This can't be expected behaviour, can it??
    Using Windows XP Home sp3
    Mucking around with C# 2008 Express
    while ( this.deadHorse ) { flog( ); }


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

    Re: Unbinding from a DataGridView, memory leak?

    I can only assume that there are additional references to those new items that take two collections to clean up. Where exactly those references are I couldn't say.
    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

  9. #9

    Thread Starter
    Fanatic Member Andy_P's Avatar
    Join Date
    May 2005
    Location
    Dunstable, England
    Posts
    669

    Re: Unbinding from a DataGridView, memory leak?

    This is my entire test project. One form, one DataGridView and three buttons:

    I have also tried binding to a list of Integers in case something odd was occurring with my custom class.


    vb Code:
    1. Private myList As BindingList(Of TrackedSet)
    2.  
    3. Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs)
    4.  
    5.     If (myList Is Nothing) Then
    6.         myList = New BindingList(Of TrackedSet)
    7.     End If
    8.  
    9.     ' Binding here needs two GC's to reclaim memory when unbinding
    10.     ' dgv.DataSource = myList
    11.  
    12.     Dim i As Integer
    13.     For i = 0 To 50000
    14.         myList.Add(New TrackedSet(i, "00000000001,123,abc"))
    15.     Next i
    16.  
    17.     ' Binding here allows memory to be reclaimed ok when unbinding
    18.     dgv.DataSource = myList
    19.  
    20. End Sub
    21.  
    22. Private Sub button2_Click(ByVal sender As Object, ByVal e As EventArgs)
    23.  
    24.     dgv.DataSource = Nothing
    25.     myList.Clear
    26.     myList = Nothing
    27.  
    28. End Sub
    29.  
    30. Private Sub button3_Click(ByVal sender As Object, ByVal e As EventArgs)
    31.  
    32.     GC.Collect
    33.  
    34. End Sub
    Using Windows XP Home sp3
    Mucking around with C# 2008 Express
    while ( this.deadHorse ) { flog( ); }


Tags for this Thread

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