SQL-запрос в Parallel.ForEach - тупик - PullRequest
2 голосов
/ 01 июня 2011

У меня есть статический метод, который вызывает SQL SP внутри статического метода в цикле Parallel.ForEach.SP вставляет данные в 3 разных таблицы.Я использую уровень Serializable Transaction.Но время от времени я сталкиваюсь с ситуацией тупика.

Я думаю, что если я сделаю этот метод в качестве метода экземпляра или использую простой 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 ]

1 голос
/ 04 июня 2012

Попробуйте изменить ваши классы на нестатические методы, которые очень помогут. НИКОГДА не используйте статику параллельно, это просто напрашивается на неприятности. А для безопасности попробуйте использовать список сохранения потоков, также известный как синхронизированный массив или System.Collections.Concurrent.ConcurrentQueue(Of T).

С уважением

0 голосов
/ 01 июня 2011

У вас проблемы, потому что вы не используете синхронизацию. Ключевое слово static не означает, что оно безопасно для потоков. Несколько потоков из Parallel.ForEach могут по-прежнему обращаться к этому методу одновременно.

У вас есть много вариантов для синхронизации. Но я начну с самого простого, сделайте его однопоточным. Если это невозможно, используйте lock или см. другие опции

UPDATE
Как заметил @Colin, мой ответ работает, если вы где-нибудь обновите данные. Если все только для чтения, то есть что-то еще. Проверьте создание DataTable.

...