C#多线程执行SQL报“未将对象引用设置到对象的实例”问题

项目中曾经用到开启一个子线程去删除一批数据,结果删除完,子线程关闭后,主线程开始狂报错,到处报“未将对象引用设置到对象的实例”。这个问题很久了也没有仔细去查,最近用户老抱怨,不得不查了。

我的项目将数据库操作对象设为了静态对象,子线程关闭会将改对象状态关闭。所以,在数据库操作类里要区分是在主线程还是在子线程中执行。

private bool IsRuninThread { get { return (System.Threading.Thread.CurrentThread.ApartmentState != System.Threading.ApartmentState.STA); } }

设置这个属性来判断是主线程还是子线程,主线程是STA,子线程是MTA。然后在构造SqlCommand以及执行操作时都要做区分:

        /// <summary>
        /// 创建数据库指令
        /// </summary>
        /// <param name="SqlString"></param>
        /// <param name="SqlParameters"></param>
        /// <returns></returns>
        public SqlCommand CreateCommand(string SqlString, SqlParameterList SqlParams)
        {
            SqlCommand cmd;
            if (IsRuninThread)  //多线程访问模式
            {
                SqlConnection con = new SqlConnection(mConnectionString);
                cmd = new SqlCommand(SqlString, con);
            }
            else
            {
                if (this.sqlTrans == null) cmd = new SqlCommand(SqlString, m_Connection);
                else cmd = new SqlCommand(SqlString, m_Connection, this.sqlTrans);
            }
            this.SetParameters(cmd, SqlParams);
            cmd.CommandTimeout = SqlOutTime;
            return cmd;
        }


       public DataSet GetDataSet(IBase Entity, string SqlStr, SqlParameterList SqlParams)
        {
            if (SqlStr == "") return null;
            using (SqlDataAdapter sda = this.CreateDataAdapter(SqlStr, SqlParams))
            {
                try
                {

                    DataSet ds = new DataSet("QueryDataSet");
                    sda.Fill(ds);
                    return ds;
                }
                catch (Exception ex)
                {
                    if (Entity != null) Entity.ErrorText = ex.Message;
                    // System.Diagnostics.Debug.Assert(false, "执行SQL出错", SqlStr + "\r\n" + ex.Message);
                    AppInfo.Debug("执行SQL" + SqlStr + "出错:" + ex.Message);
                    return null;
                }
                finally
                {
                    if (IsRuninThread) FreeCommand(sda);

                }
            }
        }

       public object ExecuteScalar(IBase Entity, SqlCommand cmd)
        {
            if (cmd == null) return null;
            try
            {
                if (IsRuninThread)
                {
                    cmd.Connection.Open();
                }
                else
                {
                    if (cmd.Connection == null) cmd.Connection = this.m_Connection;
                    this.OpenConnection();
                }
                return cmd.ExecuteScalar();
            }
            catch (Exception ex)
            {
                if (Entity != null) Entity.ErrorText = ex.Message;
                //   System.Diagnostics.Debug.Assert(false, "执行SQL出错", cmd.CommandText + "\r\n" + ex.Message);
                AppInfo.Debug("执行SQL" + cmd.CommandText + "出错:" + ex.Message);
                return null;
            }
            finally
            {
                if (IsRuninThread) FreeCommand(cmd);
                else this.CloseConnection();
            }
        }

        /// <summary>
        /// 多线程中清除线程访问的数据实例
        /// </summary>
        /// <param name="cmd"></param>
        private void FreeCommand(SqlCommand cmd)
        {
            cmd.Connection.Close();
            cmd.Connection.Dispose();
            cmd.Dispose();
        }
        /// <summary>
        /// 多线程中清除线程访问的数据实例
        /// </summary>
        /// <param name="apd"></param>
        private void FreeCommand(SqlDataAdapter apd)
        {
            apd.SelectCommand.Connection.Close();
            apd.SelectCommand.Connection.Dispose();
            apd.Dispose();
        }

这样子线程结束就不会影响主线程的正常运行啦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值