C# ASP.NETWebMethods同步
我在asp.net.asmx服务中有一个webmethod,它应该检查数据库中是否有记录,如果没有记录,它应该添加一个记录 代码的简化示例如下所示:C# ASP.NETWebMethods同步,c#,asp.net,sql,multithreading,C#,Asp.net,Sql,Multithreading,我在asp.net.asmx服务中有一个webmethod,它应该检查数据库中是否有记录,如果没有记录,它应该添加一个记录 代码的简化示例如下所示: object Mutex = new object(); [WebMethod] public void InsertIfNotExists(string CLI) { lock (Mutex) { using (SqlConnection conn = new SqlConnection(ConnectionStr
object Mutex = new object();
[WebMethod]
public void InsertIfNotExists(string CLI)
{
lock (Mutex)
{
using (SqlConnection conn = new SqlConnection(ConnectionString))
using (SqlDataAdapter adapter = new SqlDataAdapter())
using (DataSet ds = new System.Data.DataSet()){
{
//I log with log4net
logger.Debug("InsertIfNotExists: Start Function: CLI:" + CLI);
int dummy = 0;
string sql = "SELECT * CLI Promote where CLI=" + CLI + " ";
adapter.SelectCommand = new SqlCommand(sql, conn);
adapter.Fill(ds);
DataTable t = ds.Tables[0];
logger.Debug("InsertIfNotExists: " + t.Rows.Count + " records found for CLI:" + CLI);
if (t.Rows.Count == 0)
{
logger.Debug("InsertIfNotExists: starting to add to table: CLI:" + CLI);
DataRow dr = t.NewRow();
dr["CLI"] = CLI;
dr["DateOfSend"] = DateTime.Now;
InsertToTable(t, dr, sql);
logger.Debug("InsertIfNotExists: added to table: CLI:" + CLI + ", starting re-check");
//checking if exist more then one lines - one more time
sql = "SELECT * CLI Promote where CLI=" + CLI + "";
adapter.SelectCommand = new SqlCommand(sql, conn);
adapter.Fill(ds);
t = ds.Tables[0];
logger.Debug("InsertIfNotExists: re-check for CLI:" + CLI + ", records count=" + t.Rows.Count);
}
logger.Debug("InsertIfNotExists: Finish Function for CLI:" + CLI);
}
}
}
实际上,它执行更多的检查和逻辑,这就是为什么我在.net中实现它,而不是在SQL语句本身中实现它,但本质上就是这样
大多数时候代码都运行良好,但有时我会因为多线程而陷入竞争状态,尽管我使用了锁
我今天得到的示例输出:
2013-09-15 11:47:14,145 [21] DEBUG Namespace.Service1 InsertIfNotExists: Start Function: CLI: 0501234567
2013-09-15 11:47:14,145 [13] DEBUG Namespace.Service1 InsertIfNotExists: Start Function: CLI: 0501234567
2013-09-15 11:47:14,148 [21] DEBUG Namespace.Service1 InsertIfNotExists: 0 records found for CLI: 0501234567
2013-09-15 11:47:14,148 [21] DEBUG Namespace.Service1 InsertIfNotExists: starting to add to table: CLI: 0501234567
2013-09-15 11:47:14,148 [13] DEBUG Namespace.Service1 InsertIfNotExists: 0 records found for CLI: 0501234567
2013-09-15 11:47:14,148 [13] DEBUG Namespace.Service1 InsertIfNotExists: starting to add to table: CLI: 0501234567
2013-09-15 11:47:14,149 [21] DEBUG Namespace.Service1 InsertIfNotExists: added to table: CLI: 0501234567, starting re-check
2013-09-15 11:47:14,149 [13] DEBUG Namespace.Service1 InsertIfNotExists: added to table: CLI: 0501234567, starting re-check
2013-09-15 11:47:14,154 [27] DEBUG Namespace.Service1 InsertIfNotExists: Start Function: CLI: 0501234567
2013-09-15 11:47:14,157 [27] DEBUG Namespace.Service1 InsertIfNotExists: 2 records found for CLI: 0501234567
2013-09-15 11:47:14,157 [27] DEBUG Namespace.Service1 InsertIfNotExists: Finish Function for CLI: 0501234567
2013-09-15 11:47:14,183 [13] DEBUG Namespace.Service1 InsertIfNotExists: re-check for CLI: 0501234567, records count=2
2013-09-15 11:47:14,184 [21] DEBUG Namespace.Service1 InsertIfNotExists: re-check for CLI: 0501234567, records count=2
2013-09-15 11:47:14,185 [13] DEBUG Namespace.Service1 InsertIfNotExists: Finish Function for CLI: 0501234567
2013-09-15 11:49:19,626 [21] DEBUG Namespace.Service1 InsertIfNotExists: Start Function: CLI:0507654321
我们在这里看到,3个线程试图并行地将CLI 0501234567插入表中。
线程21和13进入座圈条件,每个线程插入1条记录。然后线程27也尝试插入一条记录,但找到了现有记录并退出
他们为什么在锁定互斥锁时这么做
注意:线程21永远无法完成-我认为这是由线程21中的异常引起的,因为我试图在实函数中重新检查后删除“附加”行,然后尝试执行该操作的第二个线程应该进入异常。我知道这很难看,但这是我目前唯一的解决办法,我想知道如何正确地做
为什么asp.net会以这种方式运行?在没有竞争条件的情况下,完成该任务的正确方式是什么?锁定发生的对象必须是静态的,否则服务中的每个请求都会有一个实例