2011-10-14 53 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<..,..>>