如何减少以及如何清除内存泄漏?

时间:2013-01-13 13:42:11

标签: c# winforms memory-leaks datagridview dataset

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

我的问题是:

  1. 当我读取大量数据时,如何避免“无响应”?
  2. 当我从数据库中读取时,如何减少使用的内存量(我认为我做错了什么,因为它占用了很多内存)
  3. 关闭表单后如何清除所有内存?我正在处理我所能做的一切,但似乎GC仍然没有释放内存..我读到了一些关于事件处理程序的内容并没有被处理掉?
  4. 从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万条记录(我没有注意到,因为我的脚本填满了我的数据库,我忘了阻止它)

    现在内存泄漏更容易被接受,它比我将记录添加到DataGridView之前大约多10 MB。 仍然..即使我正在使用虚拟模式并尝试关闭/处理我能做的一切,每个填充内存增长大约10 MB。

1 个答案:

答案 0 :(得分:1)

  

1)当我读取大量数据时,如何避免“无响应”?

通过在单独的线程上执行这项昂贵的任务。在WinForms中,BackgroundWorker非常有用,因为它会在作业完成后自动封送对主UI线程的调用。

  

2)如何减少我正在阅读时使用的内存量   数据库(我认为我做错了什么,因为它是一个   很多记忆)

您可以尝试启用Virtual Mode并开始对数据进行分页。一次加载25000条记录毫无用处。无论如何,用户将无法立即使用它们。

  

3)关闭表单后如何清除所有内存?我正在处理   我能做的一切,但似乎GC仍未发布   记忆..我读了一些关于事件处理程序的东西   设置?

关闭表单后,垃圾收集器将负责处理所有资源。只需确保您从未存储任何对它的引用,以使其符合GC的条件。