C# 如何减少和清除内存泄漏?

C# 如何减少和清除内存泄漏?,c#,winforms,memory-leaks,datagridview,dataset,C#,Winforms,Memory Leaks,Datagridview,Dataset,我正在从数据库读取我的Datagridview大约25000条记录。 在阅读过程中,应用程序处于“无响应”模式,我可以看到它的进程内存越来越大,停止在2500-3800 MB左右。 关闭包含Datagridview的表单后,内存仍保持此大小 我的问题是: 当我阅读大量数据时,如何避免“不响应” 当我从数据库中读取数据时,如何减少使用的内存量(我认为我做错了什么,因为内存太多了) 如何在我关闭表单后清除所有内存?我正在尽我所能处理一切,但GC似乎仍然没有释放内存。。我读了一些关于事件处理程序的东西

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

我的问题是:

  • 当我阅读大量数据时,如何避免“不响应”
  • 当我从数据库中读取数据时,如何减少使用的内存量(我认为我做错了什么,因为内存太多了)
  • 如何在我关闭表单后清除所有内存?我正在尽我所能处理一切,但GC似乎仍然没有释放内存。。我读了一些关于事件处理程序的东西,但它没有被处理
  • 从数据库读入
    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);
                    }
                }
            }
        }
    }
    
    在关闭表单后的父表单中,我调用
    ReportForm.Dispose()

    我知道
    Dispose
    不会清除内存,但它应该可以帮助GC完成它的工作,对吗

    昨晚我让应用程序开了一整夜(在我关闭了
    报告表单之后),早上的内存是一样的(GC不工作)

    提前谢谢

    编辑: 当我发现3GB内存泄漏时,我的数据库中有大约500万条记录(我没有注意到这一点,因为我有一个脚本正在填充我的数据库,我忘了停止它)

    现在,内存泄漏是可以接受的,它比我将记录添加到DataGridView之前多了大约10MB。 还是。。即使在我使用虚拟模式并尝试关闭/处置所有我能做到的东西时,每次填充内存都会增加大约10 MB

    1) 当我阅读大量数据时,如何避免“不响应”

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

    2) 当我从中读取时,如何减少使用的内存量 数据库(我认为我做错了什么,因为它是一个 大量内存)

    您可以尝试启用并开始对数据分页。一次加载25000条记录是毫无用处的。无论如何,用户永远无法同时使用它们

    3) 如何在我关闭表单后清除所有内存?我正在处理 我能做的一切,但GC似乎仍然没有发布 记忆。。我读了一些关于事件处理程序的内容,但这些内容并不是being 处置


    一旦您关闭表单,垃圾收集器将负责处理所有资源。只需确保从不存储对它的任何引用,这样它就有资格获得GC。

    您在TaskManager中看到的内容与GC没有直接关系(无论是否执行其工作)。这里没有直接的问题迹象,除了在GUI中加载25k记录是不明智的。25k是可能的最大数量,应该在2K左右,但我想让应用程序达到极限并查找bug。那么,为什么当我用
    Datagridview
    关闭winform时,计算机不清除内存?是否需要同时显示所有这些行?DataGridView是否处于虚拟模式?你的记忆问题是什么时候发生的?从数据库加载或设置DataGridView?1的数据源时。使用线程读取数据。2.不要读那么多数据。3.让GC完成它的工作。我真的不需要一次显示所有的行。我可以一次展示1000个。但是我应该能够一次将它们全部导出到CSV文件(但我可以在没有datagridview的情况下这样做,所以这不是问题)它不在
    虚拟模式下。应该是吗?当我调用此函数
    search()
    时出错,然后应用程序
    没有响应
    ,从现在起,任务管理器中的内存大小I变得越来越大,当它完成时,应用程序将“恢复正常”。谢谢。我现在检查一下。我关闭并处理了所有我能做的事情,但是在我关闭表单之后,内存仍然很大。有没有办法强制关闭所有引用?是的,有,确保没有任何引用指向此表单。您还可以尝试调用
    GC.Collect()
    来立即运行垃圾收集器。但是请注意,这通常是不好的做法,因为GC更清楚什么时候最适合运行,而不会在应用程序中创建任何争用。
    private void Reports_FormClosing(object sender, FormClosingEventArgs e)
    {
        _dbReports.Dispose();
        if (btnPress == 1)
        {
            dsReport.Dispose();
            da.Dispose();
            dbBind.Dispose();
        }
    }