Работа с семафором / мьютексом для открытия одновременных соединений с базой данных - PullRequest
0 голосов
/ 15 сентября 2018

У меня есть проблема, которая продолжалась некоторое время, и она связана с фрагментом кода, который у меня выглядит следующим образом:

Parallel.ForEach(users, new ParallelOptions { MaxDegreeOfParallelism = 8 }, user =>
{
 using(var ctx = new dbContext())
 {
   // Perform bulk update of users and the related tables 
   ctx.PerformBulkUpdateOfUser(user);
 }
});

Теперь, как вы можете видеть, проблема в том, что я открываю несколько соединений с БД (по 8 за раз), а затем выполняю 8 одновременных массовых обновлений для одной таблицы.

Проблема в том, что открытие такого большого количества соединений и выполнение такого большого количества массовых обновлений для БД, которые создают огромную кучу тупиков.

Возможные два решения, о которых я могу подумать:

  1. Реализация логики повторения
  2. Реализация семафорной / мьютексной логики, чтобы только несколько потоков могли одновременно обращаться к ресурсам БД (т. Е. Обновлять записи), а затем выполнять обновление таблицы, избегая тем самым взаимоблокировок.

Я натолкнулся на статью о реализации логики семафоров / мьютексов в c # следующим образом:

 public static Semaphore threadPool = new Semaphore(3, 5);

Приведенный выше оператор создает объект семафора с именем threadPool, который может поддерживать максимум 5 одновременных запросов.

В следующем фрагменте кода показано, как создать и запустить 10 потоков с помощью класса Thread, доступного в пространстве имен System.Threading. Обратите внимание, как был использован делегат ThreadStart.

for (int i = 0; i < 10; i++)

{

   Thread threadObject = new Thread(new ThreadStart(PerformSomeWork));

   threadObject.Name = "Thread Name: " + i;

   threadObject.Start();

}

И реализация метода "PerformSomeWork", как говорится в статье, будет выглядеть следующим образом:

private static void PerformSomeWork()

       {

           threadPool.WaitOne();

           Console.WriteLine("Thread {0} is inside the critical section...", Thread.CurrentThread.Name);

           Thread.Sleep(10000);

           threadPool.Release();

       }

Теперь с помощью этого метода и того, что было сказано выше, я вижу потенциальное решение для моей проблемы ... Итак, мои вопросы здесь:

  1. Могу ли я теперь использовать этот тип логики для одновременного обновления моей таблицы, когда только определенное количество потоков может выполнить массовое обновление таблицы.

  2. Если ответ на первый вопрос - да, как это будет выглядеть? Может ли кто-нибудь помочь мне подобрать все головоломки, чтобы у меня была более четкая картинка?

Может кто-нибудь помочь мне с этим?

...