如何减少和清除内存泄漏
本文关键字:内存 泄漏 清除 何减少 | 更新日期: 2023-09-27 17:53:13
我正在从数据库读取到我的Datagridview
大约25000条记录。在读取过程中,应用程序处于"不响应"状态。模式,我可以看到它的进程内存越来越大,停在2500-3800 MB左右。在我关闭包含Datagridview
的表单后,内存仍然保持这个大小。
我的问题是:
- 如何避免"不响应"当我读取大量数据时?
- 当我从数据库读取时,我如何减少使用的内存量(我认为我做错了什么,因为它有很多内存)
- 如何清除所有的记忆后,我关闭的形式?我正在处理我所能处理的一切,但似乎GC仍然没有释放内存…我读了一些关于事件处理程序,没有被处置?
从DB读到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);
}
}
}
}
}
当我关闭表单时:(btnPress=1
仅当我用某些东西填充Datagridview
时)
private void Reports_FormClosing(object sender, FormClosingEventArgs e)
{
_dbReports.Dispose();
if (btnPress == 1)
{
dsReport.Dispose();
da.Dispose();
dbBind.Dispose();
}
}
在父窗体中窗体关闭后我调用ReportForm.Dispose();
我知道Dispose
不清除内存,但它应该帮助GC做它的工作,对吗?
昨晚我让应用程序整夜打开(在我关闭ReportForm
之后),早上的内存是相同的(GC不工作)
当我得到3GB内存泄漏时,我的数据库大约有500万条记录(我没有注意到这一点,因为我有一个脚本正在填充我的DB,我忘了停止它)
现在内存泄漏是更可接受的,它是大约10 MB比之前我添加记录到DataGridView。还是. .即使当我使用虚拟模式并试图关闭/处置我所能做的一切时,每次填充内存增长约10 MB。
1)当我阅读大量数据时,如何避免"不响应"?
通过在单独的线程上执行这个昂贵的任务。在WinForms中,BackgroundWorker
非常有用,因为一旦任务完成,它会自动封送对主UI线程的调用。
2)我如何减少正在使用的内存量,当我从我想我做错了什么,因为它是一个大量内存)
您可以尝试启用Virtual Mode
并开始对数据进行分页。一次加载25000条记录是毫无用处的。无论如何,用户永远无法立即使用它们。
3)如何清除所有的记忆后,我关闭的形式?我处理尽我所能,但似乎GC仍然没有释放记忆. .我读了一些关于事件处理程序,不是被处理吗?
一旦您关闭窗体,垃圾收集器将负责处理所有资源。只要确保您从不存储对它的任何引用,以便它符合GC的条件。
我不小心实例化了一个表单而没有打开它…而且不处理它。引起了非常相似的症状。他们说的是真的:不要自己打电话给垃圾回收商。你有别的问题。你需要处理掉你创造的东西。我不得不检查我的代码,发现了其他几个类似的问题。