MS-Access -> OLEDB -> DataTable -> DataGridView 内存泄漏

MS-Access -> OLEDB -> DataTable -> DataGridView memory leak

我正在为 MS-Access(2016) 数据库编写胖客户端。

我的一个表单在将表单加载到数据网格视图时从数据库中检索数据。问题是关闭此表单后,内存使用量不会回落到空闲状态。应用程序在打开此表单之前使用了大约 20mb,之后是大约 200mb,关闭表单之后几乎保持在 200mb。但如果我再次打开它,它会额外消耗 200mb。

我几乎在任何地方都使用 using 块,尝试显式清空数据表,调用垃圾收集器,但没有任何帮助。

//This is the funcion being called on Form load event

    public static DataTable oledb_rs(string command)
            {

                using (OleDbConnection conn = new OleDbConnection())
                { 
                    conn.ConnectionString = Connection.ConnStr();
                    conn.Open();

                    using (OleDbCommand cmd = new OleDbCommand())
                    {

                        cmd.Connection = conn;
                        cmd.CommandType = CommandType.Text;
                        cmd.CommandText = command;


                        using (OleDbDataAdapter rs = new OleDbDataAdapter(cmd))
                        {
                            using (DataTable dt = new DataTable())
                            {
                                rs.Fill(dt);
                                return dt;
                            }
                        }
                    }

                }



            }
    //The Form load event
    using (DataTable megalldt = Connection.oledb_rs("SELECT * FROM Megallapitasok"))
                {
                    dataGridView1.DataSource = megalldt;
                }

    //The form close event
        dataGridView1.Dispose();
        this.Dispose();

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.WaitForFullGCComplete();
        GC.Collect();

DataGridView.Dispose() 对数据源(及其底层数据)做的不多,它更侧重于处理图形 (GDI+) 对象、可视列、单元格、笔、画笔等。但是它有一个参考。

因此,您需要减少内存的是确保不再有任何内容包含对 DataTable(您创建的实例)的引用。有很多方法可以做到这一点,这取决于你的对象是如何创建的,什么实例引用了什么,它们如何超出范围等等。

最简单的解决办法是关闭第二个表单,然后,dataGridView1将不再被引用(它被第二个表单引用),它的DataSource实例也是如此。然后就可以运行你的GC收集代码了