BindingList<T>, DataGridView and DataGridViewRow.Dispose

Reut Meiselman 1 Reputation point
2021-10-31T17:33:56.437+00:00

Hi,
I have BindingList<T> that is bound to DataGridView, via BindingListView<T> like:

BindingList<MyItem> _bindingListMain = new BindingList<MyItem>();
BindingListView<MyItem> _bindingListViewMain = new BindingListView<MyItem>(_bindingListMain);
dataGridViewItems.DataSource = _bindingListViewMain;

Every number of items, the list is cleared, with

_bindingListMain.Clear();

What happens with the bound DataGridViewRows? Is their Dispose function gets called? Should I call their Dispose by myself?
I get OutOfMemory exception after my application is up for a few hours and I am looking for the root cause.

Thanks

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,223 questions
{count} votes

3 answers

Sort by: Most helpful
  1. P a u l 10,406 Reputation points
    2021-10-31T18:11:39.06+00:00

    Have you tried using a memory profiler to figure out the cause or is this just a hypothesis? If you haven't profiled it I'd recommend using something like ANTS memory profiler (there's a 14 day trial period) & it's really easy to use:
    https://www.red-gate.com/products/dotnet-development/ants-memory-profiler/

    If you're running out of memory you should hopefully get a clear indication of where the memory leak is occurring.


  2. Karen Payne MVP 35,031 Reputation points
    2021-11-01T11:59:55.597+00:00

    Okay, I took an existing code sample using a BindingSource and DataTable and changed to using a BindlingList<Customer>, BindingSource to a DataGridView as shown below. Fired the application using JetBrains dotMemory.

    Overall I didn't match exactly what you are doing but instead the following shows no memory issues. If you were to do the same and still have issues best guess is there may be leaks with your DataGridView events which I've heard to be an issue which complicates issues. Perhaps if there are still leaks consider going to a ListView.

    Results from three sessions, all were within one percent of each other and in each case used a in-house custom automation tool to click the load button over 100 times.

    145531-snapshots1.png

    using System;  
    using System.ComponentModel;  
    using System.Threading.Tasks;  
    using System.Windows.Forms;  
    using LoadDataGridViewProgressBar.Classes;  
      
    namespace LoadDataGridViewProgressBar  
    {  
        public partial class BindingListForm : Form  
        {  
            private BindingSource _customersBindingSource = new BindingSource();  
            private BindingList<Customer> _customersBindingList = new BindingList<Customer>();   
            public BindingListForm()  
            {  
                InitializeComponent();  
                Shown += OnShown;  
            }  
            private async void OnShown(object sender, EventArgs e)  
            {  
                await PopulateData();  
            }  
            private async Task PopulateData()  
            {  
                var (exception, customers) = await Operations.LoadCustomerList();  
      
                if (exception == null)  
                {  
                    _customersBindingList = null;  
                    _customersBindingSource = null;  
                    customerDataGridView.DataSource = null;  
      
                    GC.Collect();  
                    await Task.Delay(500);  
      
                    _customersBindingList = new BindingList<Customer>(customers);  
                    _customersBindingSource = new BindingSource { DataSource = _customersBindingList };  
                    customerDataGridView.AutoGenerateColumns = false;  
                    customerDataGridView.DataSource = _customersBindingSource;  
                    customerDataGridView.ExpandColumns(true);  
                }  
                else  
                {  
                    // Decide how to handle any errors  
                }  
            }  
      
            private async void LoadDataGridViewButton_Click(object sender, EventArgs e)  
            {  
                await PopulateData();  
            }  
        }  
    }  
      
    

    Full source using BindingListForm.

    145513-figure1.png

    0 comments No comments

  3. Reut Meiselman 1 Reputation point
    2021-11-01T20:32:42.653+00:00

    Well, it looks like when I clear the binding list, the bound rows aren't disposed, and therefore the memory kept growing.
    After adding:

    foreach (DataGridViewRow row in dataGridViewItems.Rows)
    {
            row.Dispose();
    }
    _bindingListMain.Clear();
    GC.Collect();
    

    The memory remained low and stable.

    0 comments No comments