2015-11-11 3 views
1

У меня нет большого опыта написания хорошего многопоточного кода. Недавно я начал работать над проектом, где это необходимо. Я написал следующий код, который работает, как я хочу, однако, использование ЦП очень велико. Я предполагаю, что это связано с тем, как я использую потоки. Если кто-нибудь может указать на недостаток в приведенном ниже коде и дать мне знать, как исправить это, поэтому использование ЦП не так велико, я бы очень признателен.Высокое использование ЦП в многопоточном коде C#

var numberOfMinutes = Convert.ToInt32(ConfigurationManager.AppSettings["NumberOfMinutesToRun"]); 
var traversals = DbLayer.GetTraversals().ToList(); 
var numberOfThreads = Convert.ToInt32(ConfigurationManager.AppSettings["NumberOfThreads"]); 
var threads = new List<Thread>(numberOfThreads); 
var counter = 1; 
var s = new Stopwatch(); 
s.Start(); 
var sync = new object(); 
while (s.Elapsed < TimeSpan.FromMinutes(numberOfMinutes)) 
{ 
    for (var i = 0; i < (numberOfThreads - threads.Count); i++) 
    { 
     var counter1 = counter; // due to closure. 
     var traversal = traversals.FirstOrDefault(t => t.Id == counter1); 
     var threadStart = new ThreadStart(new CallHelper(traversal).Migrate); 
     var i1 = i; 
     threadStart +=() => 
         { 
          threads.RemoveAt(i1); 
         }; 
     threads.Insert(i, new Thread(threadStart) {IsBackground = true}); 
     threads[i].Start(); 
     lock (sync) 
     { 
      counter++; 
      if (counter > 6) 
      { 
       counter = 1; 
      } 
     } 
    } 
} 
s.Stop(); 

Я обновил код, чтобы показать, что я надеюсь, требуется, чтобы помочь мне. Коллекция обходов содержит всего 6 предметов. Счетчик предназначен для обеспечения того, чтобы потоки вращались через каждый из 6 элементов в коллекции обходов. Класс CallHelper выполняет очень долгую задачу при каждом обходе. Приложение предназначено для выполнения долговременной задачи на 6 различных объектах с использованием настраиваемого количества потоков для настраиваемого времени. Надеюсь, я заполнил достаточно пробелов.

+2

Просьба представить минимальный, полный и поддающийся проверке пример, который воспроизводит проблему. http://stackoverflow.com/help/mcve – Fabjan

+2

Я не уверен, что этот код должен делать. Какова цель здесь? Что делает 'CallHelper(). Migrate' do? Какова цель «счетчика»? Почему вы используете цикл while и цикл 'for' для генерации потоков? –

+0

Сколько потоков вы используете? и почтовый индекс о threadStart. –

ответ

0

Существует множество доступных ресурсов для написания good и эффективного многопоточного кода. «Хорошо» обычно относится к рабочему и надежному коду. Для эффективного кода используйте ресурсы embedded.

Я только отсканировал ваш код, но могу видеть множество проблем и предлагать предложения.

  1. Использование пула потоков. Строительство и срыв нитей очень дорого.
  2. Повторите цикл как можно реже (как указано выше).
  3. Используйте спит и не заняты петлями, когда вам нужно задержать.
  4. Используйте нетривиальный код для проверки эффективности. Если вы тестируете тривиальный код, ваше использование будет определяться установкой программы (а не только потоком) и срывом, что очень дорого и будет доминировать в использовании процессора.
  5. Измерить использование кода, который вас интересует, и исключить то, что вы не являетесь, например, установить приложение и снести его.
+0

Я принял это как ответ, потому что вы правы. Есть пара «проблем» с приведенным выше кодом, и, поскольку ваш ввод был очень полезным. Я переписал внутренний цикл, и использование ЦП минимально, но пропускная способность очень хорошая. Я также добавил Thread.Sleep (1000) в конец внутреннего цикла. Я также возьму совет и посмотрю, как использовать «пул потоков». Большое спасибо. – marocano1

Смежные вопросы