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.
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.