本帖最后由 lxcnn 于 2008-11-07 22:37:42 编辑

解决方案 »

  1.   

    补充一个问题,myCon这种非托管资源,是分配在哪里的?还是托管堆?
      

  2.   

    可以参考以下代码:
    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;
    } }
    }
      

  3.   

    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");
    }
      

  4.   


    数据在内存中的存储 一般是指类型存放在线程栈上 引用类型存储在托管堆上Sqlconnection 一般在一次使用完毕后 或者代码的catch代码内部需要Close的,防止程序资源冲突GC 回收是基于一种线程树的对于用户透明的结构 当内存不够或达到一个限度的时候CLR会自动调用GC回收内存 楼主的非托管资源我不明白是什么 如果是调用DLL引起的则不用过于担心 CLR加载以后会划入托管堆的管理范围 所以内存的回收也不必担心
      

  5.   

    gomoku 
    /////////////////////////////
    你说的是局部变量,如果是类中的成员呢?我确定这个sqlConnection成员不需要使用了,那么如果不把它设为null,它还是一直不会回收它,对吧?特别是我的第2个问题,  我的对象占用了很大的内存(大部分是托管资源),我调用了dispose之后, 我不把他null,那么也还是可以到达,其中的托管资源永远得不到释放(如果一直在作用域的话), 请解释一下。
      

  6.   

    我说的非托管资源,比如 sql连接,文件句柄等
      

  7.   

    补充一个问题,myCon这种非托管资源,是分配在哪里的?还是托管堆?首先,myCon本身是托管对象,活在托管堆。但一个托管对象可能拥有一些非托管资源。
      

  8.   

    特别是我的第2个问题,  我的对象占用了很大的内存(大部分是托管资源),我调用了dispose之后, 我不把他null,那么也还是可以到达,...如果你的对象占用了很大的内存,想要及时释放,那你应该在Dispose中释放。
    你确是可以在Dispose中将托管引用置零,但如果你的对象可以Dispose,一般暗示着没有其他人会再用到你的对象。既然没有其他人会用到你的对象,让系统垃圾处理不是省时又省心?