2016-10-20 2 views
0

Я пытаюсь использовать нити, чтобы вытащить вложенный список для сравнения в другой список, что-то вроде этогоThreading и список, как я иду через каждый и сравнить

List<KeyPairValues<string, List<string>> mainList = new List<KeyPairValues<string, List<string>>(); 

// In my actual code I create these list through a loop 
List<string> A = new List<string>(); 
A.Add("Car"); 
A.Add("Plain"); 
A.Add("Boat"); 

List<string> B = new List<string>(); 
B.Add("Flower"); 
B.Add("Dog"); 
B.Add("House"); 

List<string> C = new List<string>(); 
C.Add("Appartment"); 
C.Add("Plant"); 
C.Add("Candy"); 

mainList.Add(new KeyValuePair<string, List<string>>("unRead", A)); 
mainList.Add(new KeyValuePair<string, List<string>>("unRead", B)); 
mainList.Add(new KeyValuePair<string, List<string>>("unRead", C)); 

List<string> compareList = new List<string>(); 
compareList.Add("Car"); 
compareList.Add("Boat"); 
compareList.Add("Dog"); 
List<string> resList = new List<string>(); 

Моя первая мысль была используйте цикл foreach, чтобы пройти через него, в моем текущем коде у меня есть 32 списка в mainList.

foreach(var item in mainList) 
{ 
    if(item.key == "unRead") 
    { 
     foreach(var subItem in item.value) // evt do a List<string> temp = item.value first 
     { 
      foreach(var compItem in compareList) 
      { 
       if(compItem == subItem) resList.Add(compItem); 
      } 
     } 
     item.remove(); // I actualy wanted to change from unRead to read, but I figured I could just remove it from the list. 
    } 
} 

Это должно быть в состоянии быть Faste, если я использую темы и пройти через каждый список в seperat нитей, ЭВТ с максимальным количеством нитей 10 или что-то. Так что я пытался это делать.

foreach(var item in mainList) 
{ 
    Thread myThread = new Thread(() => 
    { 
     if(item.key == "unRead") 
     { 
      foreach(var subItem in item.value) // evt do a List<string> temp = item.value first 
      { 
       foreach(var compItem in compareList) 
       { 
        if(compItem == subItem) resList.Add(compItem); 
       } 
      } 
      item.remove(); // I actualy wanted to change from unRead to read, but I figured I could just remove it from the list. 
     } 
    }); 
    myThread.start(); 
} 

Но dident давать какие-либо ожидаемые результаты на всех ...

Так что я делаю неправильно?

+0

не могли бы вы указать, как выглядит ожидаемый результат и каков текущий результат? – nozzleman

+0

или это просто ускорение? – nozzleman

+0

'resList' должен быть заблокирован, поскольку он изменяется в нескольких потоках. –

ответ

2

resList следует заблокировать, поскольку он изменен в нескольких потоках. Также вам нужно подождать, пока все потоки не будут выполнены. Для этого вы должны использовать Parallel.Foreach().

Например:

Parallel.Foreach(mainList, (item) => 
{ 
    if(item.key == "unRead") 
    { 
     foreach(var subItem in item.value) // evt do a List<string> temp = item.value first 
     { 
      foreach(var compItem in compareList) 
      { 
       if(compItem == subItem) 
        lock(resList) 
         resList.Add(compItem); 
      } 
     } 
    } 
}); 

mainList.RemoveAll(item => item.key == "unRead"); 

Это может быть замкнута с некоторыми Linq магии:

Parallel.Foreach(mainList, (item) => 
{ 
    if(item.key == "unRead") 
    { 
     foreach(var subItem in item.value) // evt do a List<string> temp = item.value first 
     { 
      if(compareList.Contains(subItem)) 
       lock(resList) 
        resList.Add(compItem); 
     } 
    } 
}); 

И без резьбы/замок:

var resList = mainList.Where(item => item.key == "unRead") 
         .SelectMany(subitem => compareList.Contains(subitem))).ToList(); 

Было бы полезно использовать HashSet<> вместо List<> для compareList

+0

Вы можете найти общее с этой логикой. Список duplicates = list1.Intersect (list2) .ToList(); –

0

Как Jerone ван Langen отметил, уже, проблема заключается в том, что доступ к списку вызывает состояние гонки. Вы можете решить это, введя блокировки, или вы можете использовать реализацию коллекции, которая является потокобезопасной. Последний подход включает классы, которые работают без блокировки, что может дать вам лучшие результаты. Например, вы можете взглянуть на System.Collections.Concurrent.ConcurrentBag.

В любом случае, первая оптимизация, безусловно, будет заключаться в использовании хеш-наборов для списка сравнения, по крайней мере, если вы ожидаете, что эти списки содержат более 10 элементов (в противном случае список, вероятно, быстрее).

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