'How to reduce and how to clear the memory leak?
I'm reading from a database to my Datagridview about 25000 records.
During this reading, the application is in "not responding" mode, and I can see that its process memory is getting bigger and bigger and stops around 2500-3800 MB.
After I close the form that contains the Datagridview, the memory is remains in this size.
My questions are:
- How to avoid the "Not Responding" when I'm reading a huge amount of data?
- How can I reduce the amount of memory being used when I'm reading from the database (I think that i'm doing something wrong, becude it's a lot of memory)
- How to clear all that memory after I close the form? I'm disposing everything I can, but it's seems that the GC still not releasing the memory.. I read something about event handler that is not beeing disposed?
The code of the reading from the DB into the Datagridview:
delegate void SetSearchCallback();
public void Search()
{
sqlCommand="";
if (this._dbReports.InvokeRequired)
{
SetSearchCallback d = new SetSearchCallback(Search);
this.Invoke(d, new object[] { });
}
else
{
DateTime startDate = new DateTime(dateTimePicker1.Value.Year, dateTimePicker1.Value.Month, dateTimePicker1.Value.Day);
DateTime endDate = new DateTime(dateTimePicker2.Value.Year, dateTimePicker2.Value.Month, dateTimePicker2.Value.Day);
sqlCommand = "select * FROM cstPackages where _dateTime >= '" + String.Format("{0:yyyy-MM-dd}", startDate) + "' and _dateTime <='" + String.Format("{0:yyyy-MM-dd} 23:59:59.999", endDate) + "' order by _dateTime desc"; //reading the db from end to start
}
if (sqlCommand != "")
{
using (SqlConnection sCon2 = new SqlConnection("Data Source=" + SettingsForm.getAddress + ";Initial Catalog=" + SettingsForm.getDatabase + ";Integrated Security=False;User Id=" + SettingsForm.getUser + ";Password=" + SettingsForm.getPassword + ";Connect Timeout=5;"))
{
try
{
sCon2.Open();
using (da = new SqlDataAdapter(sqlCommand, sCon2))
{
dsReport.Clear();
da.Fill(dsReport, "cstPackages");
dbBind = new BindingSource(dsReport, "cstPackages");
if (firstTime == 0)
_dbReports.Columns.Clear();
_dbReports.DataSource = dbBind;
if (firstTime == 0)
{
updateDataGridSettings();
firstTime = 1;
}
_dbReports.Refresh();
sCon2.Close();
sCon2.Dispose();
}
}
catch (Exception c)
{
fn.errorHandler(c.Message, SettingsForm);
}
}
}
}
}
And when I'm closing the form: (btnPress=1 only if I filled the Datagridview with something)
private void Reports_FormClosing(object sender, FormClosingEventArgs e)
{
_dbReports.Dispose();
if (btnPress == 1)
{
dsReport.Dispose();
da.Dispose();
dbBind.Dispose();
}
}
And in the parent form after the form is closed I'm calling to ReportForm.Dispose();
I know that Dispose does not clear the memory, but it should help the GC to do it's job, right?
Last night I left the application open all night (After I closed the ReportForm) and the memory in the morning was the same (the GC didn't work)
Edit: When I got the 3GB memory leak, my database was with about 5 million records (I didn't notice that because I had a script that was filling my DB and I forgot to stop it)
Now the memory leak is more acceptable, it's around 10 MB more than it was before I added the records to the DataGridView. Still.. Even when I'm using virtual mode and trying to Close/Dispose everything I can, each fill the memory grows in about 10 MB.
Solution 1:[1]
1) How to avoid the "Not Responding" when I'm reading a huge amount of data?
By doing this expensive task on a separate thread. In WinForms, the BackgroundWorker is quite useful as it automatically marshals the calls to the main UI thread once the job is finished.
2) How can I reduce the amount of memory being used when I'm reading from the database (I think that i'm doing something wrong, becude it's a lot of memory)
You could try enabling Virtual Mode and start paginating your data. It's pretty useless to load 25000 records at once. The user will never be able to work with them at once anyways.
3) How to clear all that memory after I close the form? I'm disposing everything I can, but it's seems that the GC still not releasing the memory.. I read something about event handler that is not beeing disposed?
The Garbage Collector will take care of disposing all the resources once you close the form. Just make sure you never store any references to it so that it becomes eligible for GC.
Solution 2:[2]
I accidentally instantiated a form without opening it... and without disposing of it. And it caused very much the same symptoms. It really is true what they say: Do NOT call the garbage collector yourself. You have some other problem. You need to dispose of the things you create. I had to go thru my code and find a couple of other similar issues. What an insidious issue.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Darin Dimitrov |
| Solution 2 |
