/// <summary>
        /// 概述:释放当前查询结果。如果该查询结果没有放置于全局变量,应当【using】。
        /// </summary>
        public void Dispose()
        {
            if (!this._isDisposed)
            {
                this.OnDisposing();                (this._result as IDisposable).TryDispose();
                this._exception = null;
                if (this._command != null)
                {
                    this._command.Connection.TryDispose();
                    this._command.Connection = null;
                    this._command.Dispose();
                }
                this._isDisposed = true;
            }
        }这是释放资源的源代码。我想,我是不是还缺点什么?(this._result是一个DataTable)
一开始启动的时候,是10M,然后 登录+ 权限 验证进去后飙升到20M
接着,我打开包含10W条记录的表到一个新窗体的grid上。内存飙升到60M-70M左右。
可是当我关闭后,内存依旧占用着。
等到我再次打开,内存继续上升(第二次大约90M,第三次大约120M)……
加上                GC.Collect();
                GC.WaitForPendingFinalizers();
仍然没有效果。以前很少注意这点,今天忽然关注了一下, 发现自己遗漏了非常可怕的东西……
不敢怠慢,赶紧求解……

解决方案 »

  1.   

    DataTable 占用资源直接关闭窗口,很容易释放的。 是否用到其它非托管资源了?
      

  2.   

    public void Dispose()
    所处的位置 是否与 其它全局变量 处一同级 影响资源回收
      

  3.   

    数据量很大,分页获取数据
    检查程序是否需要优化
    多使用using,sqldatareader,释放资源
      

  4.   


    这个DataTable 放到 Test 类里,然后这个类放在当前窗体的全局变量里。
      

  5.   

    需要释放的  Dispose()
    最好还查看进程 。找到后kill之
      

  6.   

            /// <summary>
            /// 概述:执行查询,并返回一个数据集。
            /// </summary>
            /// <typeparam name="R">返回值类型。</typeparam>
            /// <param name="args">查询参数对象。</param>
            public DataSetResult<R> ExecuteDataSet<R>(ExecuteArgs args) where R : DataSet, new()
            {
                R result = new R();
                Exception exception = null;
                DbCommand command = this.CreateCommand(args);
                DbDataAdapter dataAdpater = this.CreateAdapter(command);
                if (args.CreateCommandBuilder) this.CreateCommandBuilder().DataAdapter = dataAdpater;
                try
                {
                    dataAdpater.Fill(result, args.TableName);
                }
                catch (Exception ex)
                {
                    this.OnThrownException(ex, command);
                    exception = ex;
                }
                finally
                {
                    command.Connection.TryClose();
                    Ex.WriteToDebug("ExecuteDataSet", command, result.ToString());
                }
                return new DataSetResult<R>(dataAdpater, command, result, exception);        }
    以上函数返回一个DataSet(当初为了支持报表而泛化)        /// <summary>
            /// 概述:执行查询,并返回一个数据集。
            /// </summary>
            /// <param name="args">查询参数对象。</param>
            public DataSetResult ExecuteDataSet(ExecuteArgs args)
            {
                var query = this.ExecuteDataSet<DataSet>(args);
                return new DataSetResult(query.DataAdapter, query.Command, query.Result, query.Exception);
            }
    以上函数返回一个DataSet,只不过调用了泛化的ExecuteDataSet<R>        /// <summary>
            /// 概述:执行查询,并返回一个数据表。
            /// </summary>
            /// <param name="args">查询参数对象。</param>
            public TableResult ExecuteTable(ExecuteArgs args)
            {
                var query = this.ExecuteDataSet(args);
                DataTable result = null;
                if (query.Success && query.Result.Tables.Count > 0)
                {
                    result = query.Result.Tables[0];
                }
                return new TableResult(query.DataAdapter, query.Command, result, query.Exception);
            }以上函数返回一个DataTable,他调用了ExecuteDataSet。类关系图:
      

  7.   

    完成后调用这个实施 
     public void Close()
        {
            if (mycon.State == ConnectionState.Open)
            {
                mycon.Close();
                mycon.Dispose();
            }
        }
      

  8.   

        /// <summary>
        /// 概述:数据库查询结果的基类。
        /// </summary>
        /// <typeparam name="R">查询结果的数据类型。</typeparam>
        public abstract class QueryResultBase<R> : IQueryResult<R>, IDisposable
        {
            /// <summary>
            /// 概述:指定参数名,返回当前【Command】的参数。
            /// </summary>
            /// <param name="parameterName">参数名。</param>
            public object this[string parameterName]
            {
                get { return this._command.Parameters[parameterName].Value; }
            }        /// <summary>
            /// 概述:指定参数索引,返回当前【Command】的参数。
            /// </summary>
            /// <param name="parameterIndex">参数索引。</param>
            public object this[int parameterIndex]
            {
                get { return this._command.Parameters[parameterIndex].Value; }
            }        /// <summary>
            /// 概述:数据库查询的结果。
            /// </summary>
            protected R _result;
            /// <summary>
            /// 概述:获取数据库查询的结果。
            /// <para>说明:查询失败将返回一个默认值(数字【0】或【null】)。</para>
            /// </summary>
            public R Result { get { return _result; } }        /// <summary>
            /// 概述:获取数据库查询时抛出的异常。
            /// </summary>
            protected Exception _exception;
            /// <summary>
            /// 概述:获取数据库查询时抛出的异常。
            /// <para>说明:默认的值为【null】。表示这个查询通过。</para>
            /// </summary>
            public Exception Exception { get { return _exception; } }        /// <summary>
            /// 概述:获取一个值,该值表示数据库查询的结果。
            /// <para>说明:当值为【true】表示数据库查询成功,否则返回【false】。</para>
            /// </summary>
            public bool Success { get { return this._exception == null; } }        private DbCommand _command;
            /// <summary>
            /// 概述:获取数据库查询时的【Command】。
            /// <para>说明:查询成功时,可以通过这个对象获取查询的【输入输出参数】以及【返回值参数】。</para>
            /// </summary>
            public DbCommand Command { get { return _command; } }        private bool _isDisposed;
            /// <summary>
            /// 概述:指示当前对象是否已被释放。
            /// </summary>
            public bool IsDisposed { get { return this._isDisposed; } }        /// <summary>
            /// 概述:初始化【V.Data.QueryResultBase】的新实例。
            /// </summary>
            /// <param name="command">命令对象。</param>
            /// <param name="result">查询结果。当查询失败时,忽视该值。</param>
            /// <param name="exception">异常对象。</param>
            internal QueryResultBase(DbCommand command, R result, Exception exception)
            {
                this._command = command;
                if (exception == null) this._result = result;
                this._exception = exception;        }        /// <summary>
            /// 概述:析构函数。
            /// </summary>
            ~QueryResultBase()
            {
                this.Dispose();
            }        /// <summary>
            /// 概述:释放当前查询结果。如果该查询结果没有放置于全局变量,应当【using】。
            /// </summary>
            public void Dispose()
            {
                if (!this._isDisposed)
                {
                    this.OnDisposing();
                    this._exception = null;
                    if (this._command != null)
                    {
                        this._command.Connection.TryDispose();
                        this._command.Connection = null;
                        this._command.Dispose();
                        this._command = null;
                    }
                    this._isDisposed = true;
                    GC.Collect();
                    GC.SuppressFinalize(this);
                }
            }        /// <summary>
            /// 概述:执行释放任务。
            /// </summary>
            protected virtual void OnDisposing()
            {
                (this._result as IDisposable).TryDispose();
            }
        }这个基类 OnDisposing()在 DataTable 和 DataSet 都包含了这么一段(但明显不合适)
            protected override void OnDisposing()
            {
                base.OnDisposing();
                this._result.Clear();// this._result = DataTable Or DataSet
                this._result.Dispose();
                this._result = null;
            }
      

  9.   

    have you solve problem ?
    congratulate you .
      

  10.   

    你的DataTable被窗体引用了,你的窗体被外面引用了,不删除引用无法释放内存
      

  11.   

    研究了一下,解决办法是错误的。
            /// <summary>
            /// 概述:释放当前查询实例以及查询据结果。
            /// </summary>
            public void Dispose()
            {
                this.Dispose(true);
            }        /// <summary>
            /// 概述:释放当前查询实例。
            /// </summary>
            /// <param name="clearResult">指示是否释放查询结果。</param>
            public void Dispose(bool clearResult)
            {
                if (!this._isDisposed)
                {
                    this.OnDisposing(clearResult);
                    this._exception = null;
                    if (this._command != null)
                    {
                        this._command.Connection.TryDispose();
                        this._command.Connection = null;
                        this._command.Dispose();
                        this._command = null;
                    }
                    this._isDisposed = true;
                    GC.Collect();
                    GC.SuppressFinalize(this);
                }
            }
      

  12.   

    这个引用是你写出来的,你检查一下new Form的地方
      

  13.   

        class Program
        {
            static void Main(string[] args)
            {
                Start();
                Console.ReadKey();
            }        static void Start()
            {
                using (var test = GetTest())
                {
                    //Do Something
                }            using (var table = GetTable())
                {
                    //Do Something
                }
            }        static Test GetTest()
            {
                return new Test();
            }        static DataTable GetTable()
            {
                return new Test().Table;
            }
        }    public class TestBase : IDisposable
        {
            private OleDbCommand _command = new OleDbCommand();
            public OleDbCommand Command { get { return this._command; } }
            public virtual void Dispose()
            {
                Console.WriteLine("来自于 TestBase 的释放...");
            }        ~TestBase()
            {
                Console.WriteLine("来自于 TestBase 的析构...");
            }
        }    public class Test : TestBase
        {
            private DataTable _table = new DataTable();
            public DataTable Table { get { return this._table; } }        public override void Dispose()
            {
                Console.WriteLine("来自于 Test 的释放...");
            }        ~Test()
            {
                Console.WriteLine("来自于 Test 的析构...");
            }
        }以上的东西该如何释放?请教高人,我想,我的情况类似这样。
      

  14.   

        class Program
        {
            static void Main(string[] args)
            {
                Start1();
                Console.ReadKey();
                Console.WriteLine("----------------------");
                Start2();
                Console.ReadKey();
            }        static void Start1()
            {
                using (var test = GetTest())
                {
                    //Do Something
                }
                GC.Collect();
            }
            static void Start2()
            {
          
                GC.Collect();
                using (var table = GetTable())
                {
                    //Do Something
                }
                GC.Collect();
            }        static Test GetTest()
            {
                return new Test();
            }        static DataTable GetTable()
            {
                return new Test().Table;
            }
        }    public class TestBase : IDisposable
        {
            private OleDbCommand _command = new OleDbCommand();
            public OleDbCommand Command { get { return this._command; } }
            public virtual void Dispose()
            {
                Console.WriteLine("1.1、来自于 TestBase 的释放...");
                GC.SuppressFinalize(this);
            }        ~TestBase()
            {
                Console.WriteLine("1.2、来自于 TestBase 的析构...");
                this.Dispose();
            }
        }    public class Test : TestBase
        {
            private DataTable _table = new DataTable();
            public DataTable Table { get { return this._table; } }        public override void Dispose()
            {
                base.Dispose();
                Console.WriteLine("2.1、来自于 Test 的释放...");
                GC.SuppressFinalize(this);
            }        ~Test()
            {
                Console.WriteLine("2.2、来自于 Test 的析构...");
            }
        }
    不知道这样的理解是否正确?
      

  15.   

       class Program
        {
            static void Main(string[] args)
            {
                Start1();
                Console.ReadKey();
                Console.WriteLine("----------------------");
                Start2();
                Console.ReadKey();
            }        static void Start1()
            {
                using (var test = GetTest())
                {
                    //Do Something
                }
                GC.Collect();
            }
            static void Start2()
            {
          
                GC.Collect();
                using (var table = GetTable())
                {
                    //Do Something
                }
                GC.Collect();
            }        static Test GetTest()
            {
                return new Test();
            }        static DataTable GetTable()
            {
                return new Test().Table;
            }
        }    public class TestBase : IDisposable
        {
            private OleDbCommand _command = new OleDbCommand();
            public OleDbCommand Command { get { return this._command; } }
            public virtual void Dispose()
            {
                Console.WriteLine("1.1、来自于 TestBase 的释放,我释放了 Command,现在 Command 已经不可以用了...");
                GC.SuppressFinalize(this);
            }        ~TestBase()
            {
                Console.WriteLine("1.2、来自于 TestBase 的析构,我准备释放 Command...");
                this.Dispose();
            }
        }    public class Test : TestBase
        {
            private DataTable _table = new DataTable();
            public DataTable Table { get { return this._table; } }        public override void Dispose()
            {
                base.Dispose();
                Console.WriteLine("2.1、来自于 Test 的释放(已调用父级释放),我释放了 Table,现在 Table 已经不可以用了...");
                GC.SuppressFinalize(this);
            }        ~Test()
            {
                Console.WriteLine("2.2、来自于 Test 的析构,我准备释放 Table...");
            }
        }
    /* 结果:1.1、来自于 TestBase 的释放,我释放了 Command,现在 Command 已经不可以用了...
    2.1、来自于 Test 的释放(已调用父级释放),我释放了 Table,现在 Table 已经不可以
    用了...
     ----------------------
    2.2、来自于 Test 的析构,我准备释放 Table...
    1.2、来自于 TestBase 的析构,我准备释放 Command...
    1.1、来自于 TestBase 的释放,我释放了 Command,现在 Command 已经不可以用了...
    2.1、来自于 Test 的释放(已调用父级释放),我释放了 Table,现在 Table 已经不可以
    用了...
    */
      

  16.   

        class Program
        {
            static void Main(string[] args)
            {
                Start1();
                Console.ReadKey();
                Console.WriteLine("----------------------");
                
                Start2();
                Console.ReadKey();
                Console.WriteLine("----------------------");
                
                Start3();
                Console.WriteLine("现在将 全局变量 _table 释放...");
                _table.Dispose();
                Console.WriteLine("现在将 全局变量 _table 置为 null 值(其实不需要这步也可以,只不过我们需要清除引用)...");
                _table = null;
                Console.WriteLine("现在将执行 GC.Collect()...");
                GC.Collect();            Console.ReadKey();
            }        static void Start1()
            {
                using (var test = GetTest())
                {
                    //Do Something
                }
                GC.Collect();
            }
            static void Start2()
            {
                using (var table = GetTable())
                {
                    //Do Something
                }
                GC.Collect();
            }        static DataTable _table;
            
            static void Start3()
            {
                _table = GetTable();
            }        static Test GetTest()
            {
                return new Test();
            }        static DataTable GetTable()
            {
                return new Test().Table;
            }
        }    public class TestBase : IDisposable
        {
            private OleDbCommand _command = new OleDbCommand();
            public OleDbCommand Command { get { return this._command; } }
            public virtual void Dispose()
            {
                if (this._command != null)
                {
                    this._command.Dispose();
                    this._command = null;
                }
                Console.WriteLine("1.1、来自于 TestBase 的释放,我释放了 Command,现在 Command 已经不可以用了...");
                GC.SuppressFinalize(this);
            }        ~TestBase()
            {
                Console.WriteLine("1.2、来自于 TestBase 的析构,我准备释放 Command...");
                this.Dispose();
            }
        }    public class Test : TestBase
        {
            private DataTable _table = new DataTable();
            public DataTable Table { get { return this._table; } }        public override void Dispose()
            {
                base.Dispose();
                if (this._table != null)
                {
                    this._table.Clear();
                    this._table.Dispose();
                    this._table = null;
                }
                Console.WriteLine("2.1、来自于 Test 的释放(已调用父级释放),我释放了 Table,现在 Table 已经不可以用了...");
                GC.SuppressFinalize(this);
            }        ~Test()
            {
                Console.WriteLine("2.2、来自于 Test 的析构,我准备释放 Table...");
            }
        }/* 显示结果:1.1、来自于 TestBase 的释放,我释放了 Command,现在 Command 已经不可以用了...
    2.1、来自于 Test 的释放(已调用父级释放),我释放了 Table,现在 Table 已经不可以
    用了...
     ----------------------
    2.2、来自于 Test 的析构,我准备释放 Table...
    1.2、来自于 TestBase 的析构,我准备释放 Command...
    1.1、来自于 TestBase 的释放,我释放了 Command,现在 Command 已经不可以用了...
    2.1、来自于 Test 的释放(已调用父级释放),我释放了 Table,现在 Table 已经不可以
    用了...
     ----------------------
    现在将 全局变量 _table 释放...
    现在将 全局变量 _table 置为 null 值(其实不需要这步也可以,只不过我们需要清除引
    用)...
    现在将执行 GC.Collect()...
    2.2、来自于 Test 的析构,我准备释放 Table...
    1.2、来自于 TestBase 的析构,我准备释放 Command...
    1.1、来自于 TestBase 的释放,我释放了 Command,现在 Command 已经不可以用了...
    2.1、来自于 Test 的释放(已调用父级释放),我释放了 Table,现在 Table 已经不可以
    用了...
    */有按照我的要求了,嘿嘿,还是自己琢磨好玩。不过不知道对不对?麻烦达人指教,劳驾各位了!
      

  17.   

    囧,效率带来的弊端呗。问题是忘了 free怎么办?从我的最终解决代码,引出了一个新的问题:频繁调用 GC.Collect()……每一次读取数据库都需要 GC.Collect(); 一下吗?
      

  18.   

    static List<Form> forms = new Form()void ShowNewForm() {
    Form1 form = new Form1()
    forms.Add(form)
    }
    这样form就删不掉了void ShowNewForm() {
    Form1 form = new Form1()
    }这样form关闭并且完成ShowNewForm后可以被释放,其中无法被释放void ShowNewForm() {
    Form1 form = new Form1()
    form.Close()
    form = null;
    GC.Collect()
    }form=null删除其引用,可以被释放,但是在第一个例子中如果form=null但是还是已经引用被添加到list里面了,也是仍然被引用,不可以释放.
      

  19.   

    大约10分钟-30分钟,系统会自动Collect一下
      

  20.   

    代码不全,不易调试。写得太复杂了,说不出准确原因。编程思路可以优化:
    (1)托管代码下,.NET的基础类,不用特殊处理。人工回收不一定比系统自动回收机制性能更好,可能更差。多余的程序代码只会增加维护成本。
    (2)按照面向对象的编程思想,尽量不要用静态类,尽量不要用全局变量。
    (3)系统设计,尽量减少层次,不是层次越多越好,而是越少越好。
    按照这种思想,改一下代码许多问题可能自动消失了,有问题也是发生在局部,很容易维护。资源回收用在真正需要用代码回收的地方,如非托管类调用,第三方控件。
      

  21.   

    曾经在博客园看到一位朋友说datatable有内存泄露(说datatable不是托管代码)。可是自己没试出来
    我们公司以前也遇到这样的问题。内存有时会占到一g多。也是由于大量读数据库产生的。
    频繁调用gc费用更高。我们改的方法是尽量减少数据的读取。限制读取的总内容。也就是bs里的分页。如果在两万之内估计不会有太大的问题。
      

  22.   


    是的。但我个人感觉,当数据量大于1W以后,应当手动collect
      

  23.   

    最终我定制了解决方案。
    我去除了析构函数,也就说,现在并不“自动”清除数据了,而是调用者“主动”Dispose。我发现,这两种在数据量小的时候,析构与collect几乎看不出任何效果。不过我的dispose的新签名增加了一个 bool 参数,指示是否应当调用collect。在调用大量数据时,就可以调用 Dispose(true)了……
    写到上面时,由于我没有做实验,猛然觉悟,不知道新签名(带有bool)是否有效?我测试了一下,令人吃惊的是,并没有预料中的减少内存(60M),诡异的是,当我关闭(关闭事件带有Dispose(true)),并打开。发现内存量并不像之前那样的不断增加20M,而是增加5m-6M后不变,再次打开,猛退到50+M,然后显示的时候又是 60M……可惜了,这样的效果难以“预料”,最终我扔了那个带参数的签名,无论如何,只要DIspose,都会执行垃圾回收。
      

  24.   

    说说不带参数的Dispose前面的测试结果。打开主界面——20M
    打开8W数据的界面——60M
    关闭8W数据的界面——45-48M。我很好奇的时候,虽然得到了垃圾回收的效果,可为什么还平白无故的多出 20M?真的是,不研究则已,越琢磨越是糊涂。
      

  25.   

    搞2个计数器,在创建dataset和datatable是分别计数,dispose中减计数器。关闭窗体时查看计数器。