15

我通过非常简单的代码进行了研究,并被困在查看数据表的 dispose() 结果

以下是代码

DataTable dt= new Datatable();
SqlCommand Cmd = new SqlCommand("sp_getData",SqlCon);
SqlCommand.CommandType= CommandType.StroedProcedure;
SqlCon.Open();
sqlDataReader dr=  cmd.ExecuteReader();
dt.Load(dr);
SqlCon.Close();
grdView.DataSource =dt;
dt.Dispose() // Here I dispose the table as it is no use for me & wanna memory free from this

但是在处理完数据表后,我仍然发现它仍然显示 RowCount = 10k。

Dispose() 方法是否不会释放内存并将对象设为空?

我怎样才能使它为空或释放这个对象占用的内存?

4

3 回答 3

25

DataSet并且DataTable实际上没有任何非托管资源,因此Dispose()实际上并没有做太多事情。和存在的Dispose()方法只是因为继承的副作用 - 换句话说,它实际上并没有在最终确定中做任何有用的事情。DataSetDataTable

事实证明 , DataSets,DataViewsDataTables它们的构造函数中抑制终结,这就是为什么显式调用Dispose()它们什么都不做的原因。

据推测,这是因为如上所述,它们没有非托管资源;因此,尽管MarshalByValueComponent考虑到非托管资源,但这些特定的实现不需要,因此可以放弃最终确定。

这个巨大答案的概述:

毫无疑问,应该在任何 Finalizable 对象上调用 Dispose。

数据表是可终结的。

调用 Dispose 显着加快了内存的回收。

MarshalByValueComponent调用GC.SuppressFinalize(this)它- 跳过这意味着在回收内存之前Dispose()必须等待数十个甚至数百个集合。Gen0

延伸阅读:

请参阅此问题和相关答案

于 2013-09-18T09:56:41.860 回答
8

Dispose() 方法是否不会释放内存并将对象设为空?

Dispose并且处置模式不是用于回收托管内存或“删除”托管对象(您不能做的事情以及垃圾收集器的用途),它用于处理非托管资源或其他可释放的托管资源的处置/释放项,例如SqlConnection. 它当然不会null作为参考,但可能会在处理前使其无法使用。

我怎样才能使它为空或释放这个对象占用的内存?

如果您想使引用为空,那么就dt = null可以了,尽管这不会给您带来任何好处,因为DataTable实例被grdView.DataSource. 两者dtgrdView.DataSource都将是对同一底层DataTable实例的引用。

我还怀疑这是一种方法的一部分,dt无论如何,这种情况都是方法范围的。

你不应该对这些东西过分担心。我会更关心/的SqlConnection外部,你有可能在那里打开连接。try-finallyusing

我倾向于呼吁Dispose实施IDisposable我认为非常好的理由的项目:这是公共合同。调用它是否做任何事情的事实是一个实现细节,并且随时可能发生变化


顺便说一句,我会完全重写你的代码:

var dt = new Datatable();

using (var conn = new SqlConnection(""))
using (var comm = new SqlCommand("sp_getData", conn))
{
    conn.Open();

    using (var reader = comm.ExecuteReader())
    {
        dt.Load(reader);
    }
}

grdView.DataSource = dt;
于 2013-09-18T09:55:59.520 回答
4

尝试使用 Clear() 函数。它非常适合我处理。

DataTable dt = GetDataSchema();
//populate dt, do whatever...
dt.Clear();
于 2013-11-20T16:52:21.560 回答