/// <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();
仍然没有效果。以前很少注意这点,今天忽然关注了一下, 发现自己遗漏了非常可怕的东西……
不敢怠慢,赶紧求解……
/// 概述:释放当前查询结果。如果该查询结果没有放置于全局变量,应当【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();
仍然没有效果。以前很少注意这点,今天忽然关注了一下, 发现自己遗漏了非常可怕的东西……
不敢怠慢,赶紧求解……
所处的位置 是否与 其它全局变量 处一同级 影响资源回收
检查程序是否需要优化
多使用using,sqldatareader,释放资源
这个DataTable 放到 Test 类里,然后这个类放在当前窗体的全局变量里。
最好还查看进程 。找到后kill之
/// 概述:执行查询,并返回一个数据集。
/// </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。类关系图:
public void Close()
{
if (mycon.State == ConnectionState.Open)
{
mycon.Close();
mycon.Dispose();
}
}
/// 概述:数据库查询结果的基类。
/// </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;
}
congratulate you .
/// <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);
}
}
{
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 的析构...");
}
}以上的东西该如何释放?请教高人,我想,我的情况类似这样。
{
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 的析构...");
}
}
不知道这样的理解是否正确?
{
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 已经不可以
用了...
*/
{
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 已经不可以
用了...
*/有按照我的要求了,嘿嘿,还是自己琢磨好玩。不过不知道对不对?麻烦达人指教,劳驾各位了!
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里面了,也是仍然被引用,不可以释放.
(1)托管代码下,.NET的基础类,不用特殊处理。人工回收不一定比系统自动回收机制性能更好,可能更差。多余的程序代码只会增加维护成本。
(2)按照面向对象的编程思想,尽量不要用静态类,尽量不要用全局变量。
(3)系统设计,尽量减少层次,不是层次越多越好,而是越少越好。
按照这种思想,改一下代码许多问题可能自动消失了,有问题也是发生在局部,很容易维护。资源回收用在真正需要用代码回收的地方,如非托管类调用,第三方控件。
我们公司以前也遇到这样的问题。内存有时会占到一g多。也是由于大量读数据库产生的。
频繁调用gc费用更高。我们改的方法是尽量减少数据的读取。限制读取的总内容。也就是bs里的分页。如果在两万之内估计不会有太大的问题。
是的。但我个人感觉,当数据量大于1W以后,应当手动collect
我去除了析构函数,也就说,现在并不“自动”清除数据了,而是调用者“主动”Dispose。我发现,这两种在数据量小的时候,析构与collect几乎看不出任何效果。不过我的dispose的新签名增加了一个 bool 参数,指示是否应当调用collect。在调用大量数据时,就可以调用 Dispose(true)了……
写到上面时,由于我没有做实验,猛然觉悟,不知道新签名(带有bool)是否有效?我测试了一下,令人吃惊的是,并没有预料中的减少内存(60M),诡异的是,当我关闭(关闭事件带有Dispose(true)),并打开。发现内存量并不像之前那样的不断增加20M,而是增加5m-6M后不变,再次打开,猛退到50+M,然后显示的时候又是 60M……可惜了,这样的效果难以“预料”,最终我扔了那个带参数的签名,无论如何,只要DIspose,都会执行垃圾回收。
打开8W数据的界面——60M
关闭8W数据的界面——45-48M。我很好奇的时候,虽然得到了垃圾回收的效果,可为什么还平白无故的多出 20M?真的是,不研究则已,越琢磨越是糊涂。