如何减少和清除内存泄漏

本文关键字:内存 泄漏 清除 何减少 | 更新日期: 2023-09-27 17:53:13

我正在从数据库读取到我的Datagridview大约25000条记录。在读取过程中,应用程序处于"不响应"状态。模式,我可以看到它的进程内存越来越大,停在2500-3800 MB左右。在我关闭包含Datagridview的表单后,内存仍然保持这个大小。

我的问题是:

  1. 如何避免"不响应"当我读取大量数据时?
  2. 当我从数据库读取时,我如何减少使用的内存量(我认为我做错了什么,因为它有很多内存)
  3. 如何清除所有的记忆后,我关闭的形式?我正在处理我所能处理的一切,但似乎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的条件。

我不小心实例化了一个表单而没有打开它…而且不处理它。引起了非常相似的症状。他们说的是真的:不要自己打电话给垃圾回收商。你有别的问题。你需要处理掉你创造的东西。我不得不检查我的代码,发现了其他几个类似的问题。