关于垃圾回收 本帖最后由 lxcnn 于 2008-11-07 22:37:42 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 补充一个问题,myCon这种非托管资源,是分配在哪里的?还是托管堆? 可以参考以下代码:using System;using System.ComponentModel;using System.Collections;using System.Diagnostics;using System.Data;using System.Data.SqlClient;using System.Configuration;namespace MyChatRoom.DataAccessLayer{ /// <summary> /// 数据访问类 /// </summary> public class Database : IDisposable { /// <summary> /// 保护变量,数据库连接。 /// </summary> protected SqlConnection Connection; /// <summary> /// 保护变量,数据库连接串。 /// </summary> protected String ConnectionString; /// <summary> /// 构造函数。 /// </summary> /// <param name="DatabaseConnectionString">数据库连接串</param> public Database() { ConnectionString = ConfigurationManager.AppSettings["DBConnectionString"]; } /// <summary> /// 析构函数,释放非托管资源 /// </summary> ~Database() { try { if (Connection != null) Connection.Close(); } catch{} try { Dispose(); } catch{} } /// <summary> /// 保护方法,打开数据库连接。 /// </summary> protected void Open() { if (Connection == null) { Connection = new SqlConnection(ConnectionString); } if (Connection.State.Equals(ConnectionState.Closed)) { Connection.Open(); } } /// <summary> /// 公有方法,关闭数据库连接。 /// </summary> public void Close() { if (Connection != null) Connection.Close(); } /// <summary> /// 公有方法,释放资源。 /// </summary> public void Dispose() { // 确保连接被关闭 if (Connection != null) { Connection.Dispose(); Connection = null; } } /// <summary> /// 公有方法,获取数据,返回一个DataSet。 /// </summary> /// <param name="SqlString">Sql语句</param> /// <returns>DataSet</returns> public DataSet GetDataSet(String SqlString) { Open(); SqlDataAdapter adapter = new SqlDataAdapter(SqlString,Connection); DataSet dataset = new DataSet(); adapter.Fill(dataset); Close(); return dataset; } /// <summary> /// 公有方法,获取数据,返回一个DataRow。 /// </summary> /// <param name="SqlString">Sql语句</param> /// <returns>DataRow</returns> public DataRow GetDataRow(String SqlString) { DataSet dataset = GetDataSet(SqlString); dataset.CaseSensitive = false; if (dataset.Tables[0].Rows.Count>0) { return dataset.Tables[0].Rows[0]; } else { return null; } } /// <summary> /// 公有方法,执行Sql语句。 /// </summary> /// <param name="SqlString">Sql语句</param> /// <returns>对Update、Insert、Delete为影响到的行数,其他情况为-1</returns> public int ExecuteSQL(String SqlString) { int count = -1; Open(); try { SqlCommand cmd = new SqlCommand(SqlString,Connection); count = cmd.ExecuteNonQuery(); } catch { count = -1; } finally { Close(); } return count; } }} SqlConnection对象的Dispose调用会断开和Sql服务器的连接,关闭Socket等(远程连接情况下)。Sql服务器只能支持有限的连接数,因此Sql连接是宝贵的资源。同理,Socket也是宝贵的资源。Dispose一般应用在要求及时释放资源的情况下。Dispose本身并不回收对象,但由于宝贵的资源已经回收了,对象本身的一点托管内存就不用理会了,垃圾回收会帮我们做好这种事的。一般不需要特别写a=null;不用把对象设为null来使它不可到达,比如Test函数中的str,调用了Test()后,谁都没有办法再调用str,str就成了垃圾回收的对象。void Test(){ StringBuilder str = new StringBuilder("hello world");} 数据在内存中的存储 一般是指类型存放在线程栈上 引用类型存储在托管堆上Sqlconnection 一般在一次使用完毕后 或者代码的catch代码内部需要Close的,防止程序资源冲突GC 回收是基于一种线程树的对于用户透明的结构 当内存不够或达到一个限度的时候CLR会自动调用GC回收内存 楼主的非托管资源我不明白是什么 如果是调用DLL引起的则不用过于担心 CLR加载以后会划入托管堆的管理范围 所以内存的回收也不必担心 gomoku /////////////////////////////你说的是局部变量,如果是类中的成员呢?我确定这个sqlConnection成员不需要使用了,那么如果不把它设为null,它还是一直不会回收它,对吧?特别是我的第2个问题, 我的对象占用了很大的内存(大部分是托管资源),我调用了dispose之后, 我不把他null,那么也还是可以到达,其中的托管资源永远得不到释放(如果一直在作用域的话), 请解释一下。 我说的非托管资源,比如 sql连接,文件句柄等 补充一个问题,myCon这种非托管资源,是分配在哪里的?还是托管堆?首先,myCon本身是托管对象,活在托管堆。但一个托管对象可能拥有一些非托管资源。 特别是我的第2个问题, 我的对象占用了很大的内存(大部分是托管资源),我调用了dispose之后, 我不把他null,那么也还是可以到达,...如果你的对象占用了很大的内存,想要及时释放,那你应该在Dispose中释放。你确是可以在Dispose中将托管引用置零,但如果你的对象可以Dispose,一般暗示着没有其他人会再用到你的对象。既然没有其他人会用到你的对象,让系统垃圾处理不是省时又省心? 关于C#自定义控件 打印功能怎么实现 OracleConnection 链接oracle怎么连接不上服务器。。求助 SQL.与.NET连接问题.非常谢谢谢谢.高分!!! 如果转换一段文字的编码? 来帮帮菜鸟... (急)asp.net 一個不能顯示界面的問題(新建一個應用程序時) VS2012环境设置 请问,C# 向sato标签打印机发送图片 通过酷Q获得登录qq的所有QQ群信息 高手来!字典范型集合做属性可以吗。。怎么实现!? >>>大家来讨论下验证码的识别咯<<<
using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
namespace MyChatRoom.DataAccessLayer
{
/// <summary>
/// 数据访问类
/// </summary>
public class Database : IDisposable
{
/// <summary>
/// 保护变量,数据库连接。
/// </summary>
protected SqlConnection Connection; /// <summary>
/// 保护变量,数据库连接串。
/// </summary>
protected String ConnectionString; /// <summary>
/// 构造函数。
/// </summary>
/// <param name="DatabaseConnectionString">数据库连接串</param>
public Database()
{
ConnectionString = ConfigurationManager.AppSettings["DBConnectionString"];
} /// <summary>
/// 析构函数,释放非托管资源
/// </summary>
~Database()
{
try
{
if (Connection != null)
Connection.Close();
}
catch{}
try
{
Dispose();
}
catch{}
} /// <summary>
/// 保护方法,打开数据库连接。
/// </summary>
protected void Open()
{
if (Connection == null)
{
Connection = new SqlConnection(ConnectionString);
}
if (Connection.State.Equals(ConnectionState.Closed))
{
Connection.Open();
}
} /// <summary>
/// 公有方法,关闭数据库连接。
/// </summary>
public void Close()
{
if (Connection != null)
Connection.Close();
} /// <summary>
/// 公有方法,释放资源。
/// </summary>
public void Dispose()
{
// 确保连接被关闭
if (Connection != null)
{
Connection.Dispose();
Connection = null;
}
} /// <summary>
/// 公有方法,获取数据,返回一个DataSet。
/// </summary>
/// <param name="SqlString">Sql语句</param>
/// <returns>DataSet</returns>
public DataSet GetDataSet(String SqlString)
{
Open();
SqlDataAdapter adapter = new SqlDataAdapter(SqlString,Connection);
DataSet dataset = new DataSet();
adapter.Fill(dataset);
Close();
return dataset;
} /// <summary>
/// 公有方法,获取数据,返回一个DataRow。
/// </summary>
/// <param name="SqlString">Sql语句</param>
/// <returns>DataRow</returns>
public DataRow GetDataRow(String SqlString)
{
DataSet dataset = GetDataSet(SqlString);
dataset.CaseSensitive = false;
if (dataset.Tables[0].Rows.Count>0)
{
return dataset.Tables[0].Rows[0];
}
else
{
return null;
}
} /// <summary>
/// 公有方法,执行Sql语句。
/// </summary>
/// <param name="SqlString">Sql语句</param>
/// <returns>对Update、Insert、Delete为影响到的行数,其他情况为-1</returns>
public int ExecuteSQL(String SqlString)
{
int count = -1;
Open();
try
{
SqlCommand cmd = new SqlCommand(SqlString,Connection);
count = cmd.ExecuteNonQuery();
}
catch
{
count = -1;
}
finally
{
Close();
}
return count;
} }
}
Sql服务器只能支持有限的连接数,因此Sql连接是宝贵的资源。同理,Socket也是宝贵的资源。Dispose一般应用在要求及时释放资源的情况下。Dispose本身并不回收对象,但由于宝贵的资源已经回收了,对象本身的一点托管内存就不用理会了,垃圾回收会帮我们做好这种事的。一般不需要特别写a=null;不用把对象设为null来使它不可到达,比如Test函数中的str,调用了Test()后,谁都没有办法再调用str,str就成了垃圾回收的对象。
void Test()
{
StringBuilder str = new StringBuilder("hello world");
}
数据在内存中的存储 一般是指类型存放在线程栈上 引用类型存储在托管堆上Sqlconnection 一般在一次使用完毕后 或者代码的catch代码内部需要Close的,防止程序资源冲突GC 回收是基于一种线程树的对于用户透明的结构 当内存不够或达到一个限度的时候CLR会自动调用GC回收内存 楼主的非托管资源我不明白是什么 如果是调用DLL引起的则不用过于担心 CLR加载以后会划入托管堆的管理范围 所以内存的回收也不必担心
/////////////////////////////
你说的是局部变量,如果是类中的成员呢?我确定这个sqlConnection成员不需要使用了,那么如果不把它设为null,它还是一直不会回收它,对吧?特别是我的第2个问题, 我的对象占用了很大的内存(大部分是托管资源),我调用了dispose之后, 我不把他null,那么也还是可以到达,其中的托管资源永远得不到释放(如果一直在作用域的话), 请解释一下。
你确是可以在Dispose中将托管引用置零,但如果你的对象可以Dispose,一般暗示着没有其他人会再用到你的对象。既然没有其他人会用到你的对象,让系统垃圾处理不是省时又省心?