C#.net在一种方法中锁定对象,而在另一种方法中不锁定对象

C#.net在一种方法中锁定对象,而在另一种方法中不锁定对象,c#,object,static,locking,C#,Object,Static,Locking,我有两个方法“ExecuteNoQuery”(执行dbCommand.ExecuteNonQuery())和“Query”执行(dbCommand.ExecuteReader())。 这两种方法都使用相同的连接对象。在ExecuteNoQuery方法中,实现了一个锁(使用连接对象)和一个查询方法(使用out锁)。如果有多个线程,不同的线程同时访问两个方法,那么会发生什么 注意:在查询方法中,自定义连接池是用同一个对象实现的 public int ExecuteNoQuery(string sql

我有两个方法“ExecuteNoQuery”(执行dbCommand.ExecuteNonQuery())和“Query”执行(dbCommand.ExecuteReader())。 这两种方法都使用相同的连接对象。在ExecuteNoQuery方法中,实现了一个锁(使用连接对象)和一个查询方法(使用out锁)。如果有多个线程,不同的线程同时访问两个方法,那么会发生什么

注意:在查询方法中,自定义连接池是用同一个对象实现的

public int ExecuteNoQuery(string sqlquery, Hashtable htData) {
try {
 lock(Myservice.dbcon)  
  {
    using (OracleCommand dbCommand = new OracleCommand(sqlquery, Myservice.dbcon)) 
        {

              int rowCount = dbCommand.ExecuteNonQuery();
              return 1;
        }
  }
}


public OracleDataReader Query(string sqlquery, Hashtable htData)
    {
        try
        {
            OracleDataReader dbReader = null;
            Random ran = new Random();
            int randomnumber = ran.Next(1,5);

           Myservice.dbcon = (OracleConnection) Myservice.htdbcon
           ["Connection_" +randomnumber];

            if (Myservice.dbcon.State != System.Data.ConnectionState.Executing 
              || Myservice.dbcon !=  System.Data.ConnectionState.Fetching)
                {
                    using (OracleCommand dbCommand = new OracleCommand(sqlquery,
                     Myservice.dbcon))
                    { 

                        dbReader = dbCommand.ExecuteReader();
                    }
                }
                return dbReader;

        }
这两种方法都使用相同的连接对象

因为一种方法使用锁,而另一种方法不使用锁:糟糕的事情。对于这个场景,对象没有做出任何保证,因此您应该期望它以有趣的方式失败。您应该在两个位置使用相同的锁对象,或者更好:仅在隔离代码中使用连接,而不是共享连接。对于连接池,在某个地方有一个共享连接对象很少有用。一种更合适的模式通常是在需要时获得连接,然后进行处理。如果基础提供程序支持池,则这将在理想情况下执行,不会出现任何同步问题,并允许并行查询等。例如:

using (var conn = SomeUtilityClass.GetOpenConnection())
using (var cmd = conn.CreateCommand()) 
{
    cmd.CommandText = sqlquery;
    int rowCount = dbCommand.ExecuteNonQuery();
    return 1;
}
而且,重要的是,从
Query
方法执行相同的操作;没有锁,没有全局共享连接

顺便说一句,我还担心缺少参数。这表明您正在向SQL注入错误敞开大门

这两种方法都使用相同的连接对象

因为一种方法使用锁,而另一种方法不使用锁:糟糕的事情。对于这个场景,对象没有做出任何保证,因此您应该期望它以有趣的方式失败。您应该在两个位置使用相同的锁对象,或者更好:仅在隔离代码中使用连接,而不是共享连接。对于连接池,在某个地方有一个共享连接对象很少有用。一种更合适的模式通常是在需要时获得连接,然后进行处理。如果基础提供程序支持池,则这将在理想情况下执行,不会出现任何同步问题,并允许并行查询等。例如:

using (var conn = SomeUtilityClass.GetOpenConnection())
using (var cmd = conn.CreateCommand()) 
{
    cmd.CommandText = sqlquery;
    int rowCount = dbCommand.ExecuteNonQuery();
    return 1;
}
而且,重要的是,从
Query
方法执行相同的操作;没有锁,没有全局共享连接


顺便说一句,我还担心缺少参数。这意味着您将面临SQL注入错误。

我的应用程序很少出现挂起的情况。当分析日志时,我发现挂起是由于同时访问两个方法造成的。它不会给出任何例外(C#/Oracle)。知道挂起的原因是什么吗?@user2075249因为您错误地使用了它,让两个线程同时使用连接。线程问题最令人烦恼的一部分是,它们不会立即且始终显示出来——只有在无效使用导致问题时,例如损坏字段的内部状态、错误地将交错数据发送到应设置帧的套接字或错误地读回数据。基本上你所做的是错误的。您必须立即停止使用来自多个线程的连接。我的应用程序很少出现挂起的情况。当分析日志时,我发现挂起是由于同时访问两个方法造成的。它不会给出任何例外(C#/Oracle)。知道挂起的原因是什么吗?@user2075249因为您错误地使用了它,让两个线程同时使用连接。线程问题最令人烦恼的一部分是,它们不会立即且始终显示出来——只有在无效使用导致问题时,例如损坏字段的内部状态、错误地将交错数据发送到应设置帧的套接字或错误地读回数据。基本上你所做的是错误的。必须立即停止使用来自多个线程的连接。