2013-05-28 5 views
1

Я следующий кодБезопасное добавление в список в Parallel.ForEach

var myResponse = new Response(); 
Parallel 
.ForEach(itemsListDto 
     , new ParallelOptions { MaxDegreeOfParallelism = 10 } 
     , itemDto => { 
         var tResponse = _itemService 
             .InsertItem 
              (itemDto 
              , new RequestMessage 
                {UserName = RequestUserName}); 
          myResponse.AddErrors(tResponse.Errors); 
         } 
     ); 
return myResponse; 

Кажется, что myResponse не получает все Errors добавил к нему. Как я должен переписать это, чтобы быть в безопасности?

+0

Пожалуйста, разместите определение 'AddErrors'. – Lee

ответ

4

Вам нужно будет синхронизировать доступ к myResponse, так как это звучит, как метод AddErrors не поточно:

var myResponse = new Response(); 
var syncObj = new object(); 
Parallel.ForEach(itemsListDto, new ParallelOptions { MaxDegreeOfParallelism = 10 }, itemDto => 
    { 
     var tResponse = _itemService.InsertItem(itemDto, new RequestMessage {UserName = RequestUserName}); 
     lock(syncObj) 
      myResponse.AddErrors(tResponse.Errors); 
    }); 
return myResponse; 

Если InsertItem это довольно длительный процесс, это может быть приемлемым с точки зрения производительности.

Если InsertItem является довольно быстрым методом, это может привести к большому количеству накладных расходов на синхронизацию и вызвать общее время приближения к синхронному циклу. В этом случае вы можете использовать перегрузки Parallel.ForEach which provide local state для блокировки реже и сохранять ошибки в своем локальном состоянии, а затем агрегировать в конце полного цикла. У меня есть статья, подробно описывающая process required to aggregate data efficiently using Parallel.ForEach.

+0

Я реализовал Агрегацию, отлично работает, спасибо! – CaffGeek