Parallel.ForEach中的SQL查询 - 死锁

时间:2011-06-01 14:08:16

标签: c# sql-server multithreading parallel-processing

我有一个静态方法,它在Parallel.ForEach循环中的静态方法中调用SQL SP。 SP在3个不同的表中插入数据。我正在使用Serializable Transaction级别。但有一段时间我遇到了僵局的情况。

我在想,如果我将该方法作为Instance方法或使用简单的ForEach,它可能会解决问题。

我在想什么?我是否也需要锁定列表?

- 代码 -

Parallel.ForEach(MyConcurrentDictionary, MyElement =>
{
   if (MyElement.SomeProperty != SomeValue)
      {
         PublishMessage(MyElement);
      }
      else
      {
         InsertInDatabase(MyElement);

      }
}




public static void InsertInDatabase()
{
   DataTable t1 = new DataTable();
   DataTable t2 = new DataTable();
   DataTable t3 = new DataTable();


   CreateTable(T1);
   CreateTable(T2);
   CreateTable(T3);

   using (var conn = new SqlConnection(ConnString))
      {
         try
            {
               conn.Open();

               // Begin transaction
               using (SqlTransaction transaction = conn.BeginTransaction(IsolationLevel.Serializable))
                  {
                     SqlCommand cmd = new SqlCommand();
                     cmd.Transaction = transaction;
                     cmd.Connection = conn;
                     cmd.CommandType = CommandType.StoredProcedure;
                     cmd.CommandText = "SPName";
                     cmd.Parameters.AddWithValue("@T1", T1);
                     cmd.Parameters.AddWithValue("@T2", T2);
                     cmd.Parameters.AddWithValue("@T3", T3);
                     cmd.ExecuteNonQuery();

                     transaction.Commit();

                }
           }

     }
}

2 个答案:

答案 0 :(得分:1)

尝试将您的类更改为非静态方法,这将有很大帮助。永远不要同时使用静力学它只是在寻找麻烦。为了安全起见,尝试使用线程保存列表,即同步化的arraylist或System.Collections.Concurrent.ConcurrentQueue(Of T)

亲切的问候

答案 1 :(得分:0)

由于您不使用任何同步,因此会出现问题。关键字static并不意味着它是线程安全的。来自Parallel.ForEach的多个线程仍然可以同时访问此方法。

你有很多选择来同步它。但我将从最简单的一个开始,使其成为单线程。如果无法使用,请使用lock或查看other options

UPDATE
正如@Colin所注意到的,如果你在某处更新数据,我的答案是有效的。如果一切都是只读的,那么还有其他的东西。检查DataTable的创建。