2011-10-14 47 views
0

我正在嘗試使用groupby語句在其中並行查詢。查詢類似於Parallel.ForEach和IGrouping源項目問題

var colletionByWeek = (
          from item in objectCollection 
          group item by item.WeekStartDate into weekGroups 
          select weekGroups 
         ).ToList(); 

如果我使用Parallel.ForEach共享變量像下面,它工作正常。但我不想在並行查詢中使用共享變量。

var pSummary=new List<object>(); 
Parallel.ForEach(colletionByWeek, week => 
           { 
            pSummary.Add(new object() 
            { 
             p1 = week.First().someprop, 
             p2= week.key, 
             ..... 
            }); 
           } 
       ); 

所以,我已經改變了上面的並行語句使用局部變量。但編譯器抱怨源類型<IEnumerable<IGrouping<DateTime, object>>無法轉換爲System.Collections.Concurrent.OrderablePartitioner<IEnumerable<IGrouping<DateTime, object>>

我給錯了源類型?或者這種類型的IGouping類型處理方式不同?任何幫助,將不勝感激。謝謝!

Parallel.ForEach<IEnumerable<IGrouping<DateTime, object>>, IEnumerable<object>> 
         (spotColletionByWeek, 
         () => new List<object>(), 
         (week, loop, summary) => 
         { 
          summary.Add(new object() 
          { 
              p1 = week.First().someprop, 
              p2= week.key, 
              ..... 
          }); 
          return new List<object>(); 
         }, 
         (finalResult) => pSummary.AddRange(finalResult) 
         ); 
+2

列表不是線程安全的。改爲使用['ConcurrentBag '](http://msdn.microsoft.com/en-us/library/dd381779.aspx)。 –

回答

2

類型參數TSource是元素類型,而不是集合類型。而第二個類型參數表示本地存儲類型,所以它應該是List<T>,如果你想要Add()就可以了。這應該工作:

Parallel.ForEach<IGrouping<DateTime, object>, List<object>> 

這是假設你實際上並沒有object在那兒,但某些特定的類型。

雖然在這裏甚至不需要顯式類型參數。編譯器應該能夠推斷出它們。

但也有代碼的其他問題:

  • 你不應該從主要代表返回新List,但summary

  • 處理該委託finalResult可能會在多個併發執行線程,所以你應該在那裏使用鎖或併發集合。

1

我要跳過「你確定你甚至需要優化這個」階段,並假設你有你希望通過並行來解決性能問題。

首先,你沒有試圖用Parallel.Foreach<>來完成這個任務。我敢肯定你會得到一個可讀性和更優化的結果使用PLINQ:

var random = new Random(); 
var weeks = new List<Week>(); 
for (int i=0; i<1000000; i++) 
{ 
    weeks.Add(
     new Week { 
      WeekStartDate = DateTime.Now.Date.AddDays(7 * random.Next(0, 100)) 
     }); 
} 

var parallelCollectionByWeek = 
    (from item in weeks.AsParallel() 
    group item by item.WeekStartDate into weekGroups 
    select new 
    { 
     p1 = weekGroups.First().WeekStartDate, 
     p2 = weekGroups.Key, 
    }).ToList(); 

值得一提的有是並行的GroupBy運營商相關的一些開銷,因此受益的將是少量的最好。 (一些粗糙的基準提示加快10-20%)

除此之外,你得到編譯錯誤的原因是因爲第一個類型參數應該是IGrouping<DateTime, object>而不是IE<IG<..,..>>