不同Thread中使用相同OledbConnect 实例的问题
环境:win2003+vs2003+oracle9i
有下面的类:
 using System;
using System;
 using System.Data;
using System.Data;
 using System.Data.OleDb;
using System.Data.OleDb;
 namespace MyData
namespace MyData
 {
{    
 public class OraData
    public class OraData
 {
    {
 private OleDbConnection Con=new OleDbConnection();            //数据库联接
        private OleDbConnection Con=new OleDbConnection();            //数据库联接
 public OraData()
       public OraData()
 {
      {
 //给Con的字符串赋值
         //给Con的字符串赋值
 Con.ConnectionString="
         Con.ConnectionString=" ";
";
 }
      }
 public bool HaveData(string table)
      public bool HaveData(string table)
 {
     {            
 
            
 if(Con.State==ConnectionState.Closed)
         if(Con.State==ConnectionState.Closed)
 {
        {
 Con.Open();
               Con.Open();
 }
         }
 OleDbCommand cmd=Con.CreateCommand();
        OleDbCommand cmd=Con.CreateCommand();
 cmd.CommandText="select count(*) from "+table;
        cmd.CommandText="select count(*) from "+table;
 int count=Convert.ToInt32(cmd.ExecuteScalar().ToString());
        int count=Convert.ToInt32(cmd.ExecuteScalar().ToString());
 if(count==0) then
        if(count==0) then
 {return false;}
        {return false;}
 else
         else
 {    return true;  }
       {    return true;  }
 }
     }
 }
  }
 }如果在其他类中用MultiThread调用这个方法:
}如果在其他类中用MultiThread调用这个方法:
 using System;
using System;
 using System.Threading;
using System.Threading;
 namespace MyData
namespace MyData
 {
{
 public class Test
  public class Test
 {
  {
 private OraData data=new OraData();
       private OraData data=new OraData();
private Thread work;
private void do()
{
while(true)
{
data.HaveData("ta");
}
}
private void Dowork()
{
while(true)
{
data.HaveData("tb");
}
}
private void doagain()
{
work=new Thread(new ThreadStart(Dowork));
work.Start();
}
 }
   }
 }
}
如果只调用do(),那么没问题,一切正常,如果执行过程中在调用了dogain(),那么会发生异常,导致Thread work终止,而且原先进程的do()也会有异常,用try..catch捕获异常得到:
都是“未将对象引用设置到对象的实例。”指向的都是Con。
同时还有“ExecuteScalar 需要打开的并且可用的连接。该连接的当前状态是 Open, Executing。”,指向了HaveData().
觉得很奇怪,既然说Con没有将对象引用设置到对象实例,那么怎么会执行ExecuteScalar(),而且Con是建立了Pooling的,即使程序请求多个数据库联接,也是没问题的。
既然问题发生在2个进程使用相同的OledbConnection,而单个Thread的操作没有问题,那么说明有Pooling的相同OleDbConnection实例,面对2个Thread时工作有问题。
 
如果把Con设为static,又没有效果呢?
测试了一下,还会出现“ExecuteScalar 需要打开的并且可用的连接。该连接的当前状态是 Open, Executing。”错误。那只能理解为Pooling面对2个Thread工作有问题。
那么该怎样解决呢?
我用的方法是:建立另一个OleDbConnection,
private OledbConnection AnotherCon =new OleDbConnection();
放在Con的下面,OraData的构造函数中加入AnotherCon的ConnectionString,
在HaveData()中判断操作的表,根据不同的表使用不同的OleDbConnection,经过测试没有问题。
深层原因,还在查资料,有了结果,再做补充。
目前结论:
OleDbConnection对象,在MultiThread中是不安全的,不论使用实例还是静态方法。
所以建议每个工作进程都使用自己的OleDbConnection对象。
谢谢回复:
因为Thread,翻译成进程、线程似乎都可以,为了描述准确,文章中全部使用Thread,谢谢大家的理解。
欢迎大家发表见解。
 
有下面的类:
 using System;
using System; using System.Data;
using System.Data; using System.Data.OleDb;
using System.Data.OleDb; namespace MyData
namespace MyData {
{     public class OraData
    public class OraData {
    { private OleDbConnection Con=new OleDbConnection();            //数据库联接
        private OleDbConnection Con=new OleDbConnection();            //数据库联接 public OraData()
       public OraData() {
      { //给Con的字符串赋值
         //给Con的字符串赋值 Con.ConnectionString="
         Con.ConnectionString=" ";
"; }
      } public bool HaveData(string table)
      public bool HaveData(string table) {
     {             
             if(Con.State==ConnectionState.Closed)
         if(Con.State==ConnectionState.Closed) {
        { Con.Open();
               Con.Open(); }
         } OleDbCommand cmd=Con.CreateCommand();
        OleDbCommand cmd=Con.CreateCommand(); cmd.CommandText="select count(*) from "+table;
        cmd.CommandText="select count(*) from "+table; int count=Convert.ToInt32(cmd.ExecuteScalar().ToString());
        int count=Convert.ToInt32(cmd.ExecuteScalar().ToString()); if(count==0) then
        if(count==0) then {return false;}
        {return false;} else
         else {    return true;  }
       {    return true;  } }
     } }
  } }
} using System;
using System; using System.Threading;
using System.Threading; namespace MyData
namespace MyData {
{ public class Test
  public class Test {
  { private OraData data=new OraData();
       private OraData data=new OraData();private Thread work;
private void do()
{
while(true)
{
data.HaveData("ta");
}
}
private void Dowork()
{
while(true)
{
data.HaveData("tb");
}
}
private void doagain()
{
work=new Thread(new ThreadStart(Dowork));
work.Start();
}
 }
   } }
}如果只调用do(),那么没问题,一切正常,如果执行过程中在调用了dogain(),那么会发生异常,导致Thread work终止,而且原先进程的do()也会有异常,用try..catch捕获异常得到:
都是“未将对象引用设置到对象的实例。”指向的都是Con。
同时还有“ExecuteScalar 需要打开的并且可用的连接。该连接的当前状态是 Open, Executing。”,指向了HaveData().
觉得很奇怪,既然说Con没有将对象引用设置到对象实例,那么怎么会执行ExecuteScalar(),而且Con是建立了Pooling的,即使程序请求多个数据库联接,也是没问题的。
既然问题发生在2个进程使用相同的OledbConnection,而单个Thread的操作没有问题,那么说明有Pooling的相同OleDbConnection实例,面对2个Thread时工作有问题。
如果把Con设为static,又没有效果呢?
测试了一下,还会出现“ExecuteScalar 需要打开的并且可用的连接。该连接的当前状态是 Open, Executing。”错误。那只能理解为Pooling面对2个Thread工作有问题。
那么该怎样解决呢?
我用的方法是:建立另一个OleDbConnection,
private OledbConnection AnotherCon =new OleDbConnection();
放在Con的下面,OraData的构造函数中加入AnotherCon的ConnectionString,
在HaveData()中判断操作的表,根据不同的表使用不同的OleDbConnection,经过测试没有问题。
深层原因,还在查资料,有了结果,再做补充。
目前结论:
OleDbConnection对象,在MultiThread中是不安全的,不论使用实例还是静态方法。
所以建议每个工作进程都使用自己的OleDbConnection对象。
谢谢回复:
因为Thread,翻译成进程、线程似乎都可以,为了描述准确,文章中全部使用Thread,谢谢大家的理解。
欢迎大家发表见解。
 
                     
                    
                 
                    
                 
                
            
         
 
         浙公网安备 33010602011771号
浙公网安备 33010602011771号