I'm writing a thick client to an MS-Access(2016) database.
One of my forms retrieves data from the database on form loading into a datagridview. The issue is that after closing this form, the memory usage doesnt drop back to idle. App uses about 20mb before opening this form, after is about 200mb, and after closing the form pretty much stays at 200mb. But if i open it again it will consume an additional 200mb.
I'm using using block almost everywhere, tried explicitly nulling the datatable, call garbage collector, but nothing helps.
//This is the funcion being called on Form load event
public static DataTable oledb_rs(string command)
{
using (OleDbConnection conn = new OleDbConnection())
{
conn.ConnectionString = Connection.ConnStr();
conn.Open();
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = command;
using (OleDbDataAdapter rs = new OleDbDataAdapter(cmd))
{
using (DataTable dt = new DataTable())
{
rs.Fill(dt);
return dt;
}
}
}
}
}
//The Form load event
using (DataTable megalldt = Connection.oledb_rs("SELECT * FROM Megallapitasok"))
{
dataGridView1.DataSource = megalldt;
}
//The form close event
dataGridView1.Dispose();
this.Dispose();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.WaitForFullGCComplete();
GC.Collect();
DataGridView.Dispose() doesn't do much about the datasource (and its underlying data), it's more focused on disposing graphical (GDI+) objects, visual columns, cells, pens, brushes, etc. But it has a reference on it.
So, what you need to reduce memory is ensure nothing holds a reference to the DataTable (the instance you created) anymore. There are many ways to do it, it depends how your objects are created, what instance references what, how they go out of scope, etc.
The most simple solution is to close the 2nd form, then, dataGridView1 will not be referenced anymore (it was referenced by the 2nd form), same for its DataSource instance. Then you can run your GC collection code.