0

я использую Task Parallel Library (TPL) и C# 4.5, чтобы реализовать эту бизнес-логику в приложения-службы Windows:Изменение Parallel.ForEach для лучшего подхода

  • Получить JSON результат (список) из удаленного RESTful API
  • для каждого элемента, получить JSON результата деталей из другого удаленного RESTful API
  • для каждого элемента прикрепленной бизнес-объектов (1000+), используйте Parallel.ForEach сохранения в базу данных

В настоящее время проблема заключается в сохранении каждого элемента в базе данных (Sync DAL), поэтому Parallel.ForEach 1000 элементов выполняется навсегда, а приложение Windows Service работает медленнее и медленнее. У кого-нибудь есть хорошие идеи или лучший подход к повышению производительности?

Фрагмент кода:

/* Download a list from RESTful API URL.... */ 
var task = Task.Factory.StartNew(() => { return DownloadListFromRestAPI(); }, TaskCreationOptions.LongRunning); 
task.ContinueWith(i => { 
    foreach (var r in i.Result) 
     { 
      /* For each item, download the item details from RESTful API URL.... */ 
      var taskSecond = Task.Factory.StartNew(() => { return DownloadItemDetailFromRestAPI(r.id); }, TaskCreationOptions.LongRunning); 
      taskSecond.ContinueWith(m => { 
       /* For each item detail, get the related business objects, and start Database operation on each object.... */ 
       List<Item> relatedItems_1000 = s.GetRelatedObjectsIds(m.Result.id); 

       /* parallel.ForEach - 1000 or more items */ 
       Parallel.ForEach<Item>(relatedItems_1000, new ParallelOptions { MaxDegreeOfParallelism = 8 }, d => DBLongProcess(d)); /* The DB operation takes long time */ 
      }); 
     } 
}); 

Update: (код для DBLongProcess() и замок (я добавил замок, потому что одновременно потоки могут пытаться изменить тот же объект в БД))

private void DBLongProcess(Item item) 
{ 
    dbDAL.InsertObjectDB(item)); 
} 

public class DBDAL 
{ 
     private readonly object _lock = new object(); 

     public void InsertObjectDB(Item item) 
     { 
      lock (_lock) 
      { 
      if(!item.hasDetail1()){ 
       //insert item.detail1... 
      } 
       if(!item.hasDetail2()){ 
       //insert item.detail2 
      } 
      } 
     } 
} 
+0

Как «DBLongProcess» обеспечивает безопасность потоков? Если все сделано неправильно, это может стать источником вашей медлительности. Можете ли вы включить код для этого тоже? –

+0

@ScottChamberlain, см. Мои обновления. Спасибо вам! – xoyoja

+0

Неясно, в чем проблема. UI замедляется, потому что Background занимает слишком много ресурсов? – Nahum

ответ

3

В вашем случае использование Parallel.ForEach() не ускорит ничего, потому что lock в InsertObjectDB() заставляет все элементы вставлять их последовательно.

Что вам нужно сделать, это нарисовать способ сделать DBDAL поточно-безопасным (возможно, используя несколько экземпляров его). Если это не осуществимо, вам придется искать улучшения производительности в других местах.

+0

Спасибо. Если блокировка удалена и DBDAL является потокобезопасной, Parallel.ForEach (1000+ элементов) - лучший подход к высокой производительности в моем случае? – xoyoja

+0

Трудно сказать, не зная подробностей вашей реализации. – svick

+0

Хотя я отметил это как ответ, это не означает, что проблема решена. Сначала я буду отслеживать/отслеживать код, чтобы увидеть, сколько времени тратится большая часть времени. Затем я попытаюсь удалить блокировку и сделать поток DAL безопасным. Я буду использовать более безопасную для кэширования стратегию кэширования и немедленно передать все данные в БД. – xoyoja

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