C#.net在一种方法中锁定对象,而在另一种方法中不锁定对象
我有两个方法“ExecuteNoQuery”(执行dbCommand.ExecuteNonQuery())和“Query”执行(dbCommand.ExecuteReader())。 这两种方法都使用相同的连接对象。在ExecuteNoQuery方法中,实现了一个锁(使用连接对象)和一个查询方法(使用out锁)。如果有多个线程,不同的线程同时访问两个方法,那么会发生什么 注意:在查询方法中,自定义连接池是用同一个对象实现的C#.net在一种方法中锁定对象,而在另一种方法中不锁定对象,c#,object,static,locking,C#,Object,Static,Locking,我有两个方法“ExecuteNoQuery”(执行dbCommand.ExecuteNonQuery())和“Query”执行(dbCommand.ExecuteReader())。 这两种方法都使用相同的连接对象。在ExecuteNoQuery方法中,实现了一个锁(使用连接对象)和一个查询方法(使用out锁)。如果有多个线程,不同的线程同时访问两个方法,那么会发生什么 注意:在查询方法中,自定义连接池是用同一个对象实现的 public int ExecuteNoQuery(string sql
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因为您错误地使用了它,让两个线程同时使用连接。线程问题最令人烦恼的一部分是,它们不会立即且始终显示出来——只有在无效使用导致问题时,例如损坏字段的内部状态、错误地将交错数据发送到应设置帧的套接字或错误地读回数据。基本上你所做的是错误的。必须立即停止使用来自多个线程的连接。