简体   繁体   中英

SQL query in Parallel.ForEach - Deadlock

I have a static method which calls SQL SP inside a static method in a Parallel.ForEach loop. SP inserts data in 3 different tables. I am using Serializable Transaction level. But once in a while i am running into Deadlock situation.

I am thinking that if i make that method as Instance method or use simple ForEach, it may fix the problem.

Am i thinking right? Do i need to lock the list as well?

--Code--

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();

                }
           }

     }
}

Try to change your classes to non static methods that will help a lot. NEVER use statics in parallel it is just asking for trouble. And for safety try to use a thread save list aka an syncronized arraylist or a System.Collections.Concurrent.ConcurrentQueue(Of T) .

Kind regards

You get problems because you do not use any synchronization. The keyword static does not mean it is thread safe. Multiple threads from Parallel.ForEach can still access this method at the same time.

You have many options to synch that. But I will start with the easiest one, make it single threaded. If not possible, use lock or see other options

UPDATE
As noticed by @Colin, my answer works if you update the data somewhere. If everything is read-only, there is something else then. Check creation of the DataTable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM