使用PLINQ计算和更新机箱内的值不起作用

时间:2010-05-07 15:24:24

标签: c# c#-4.0 plinq

我最近需要在报告上执行总计。对于每个组,我按行排序,然后根据组中的先前行计算运行总计。啊哈!我想,PLINQ是一个完美的用例!

但是,当我编写代码时,我得到了一些奇怪的行为。我正在修改的值显示在步进调试器时被修改,但是当它们被访问时它们总是为零。

示例代码:

class Item
{
 public int PortfolioID;
 public int TAAccountID;
 public DateTime TradeDate;
 public decimal Shares;
 public decimal RunningTotal;
}

List<Item> itemList = new List<Item>
{
 new Item
 {
  PortfolioID = 1,
  TAAccountID = 1,
  TradeDate = new DateTime(2010, 5, 1),
  Shares = 5.335m,
 },
 new Item
 {
  PortfolioID = 1,
  TAAccountID = 1,
  TradeDate = new DateTime(2010, 5, 2),
  Shares = -2.335m,
 },
 new Item
 {
  PortfolioID = 2,
  TAAccountID = 1,
  TradeDate = new DateTime(2010, 5, 1),
  Shares = 7.335m,
 },
 new Item
 {
  PortfolioID = 2,
  TAAccountID = 1,
  TradeDate = new DateTime(2010, 5, 2),
  Shares = -3.335m,
 },

};

var found = (from i in itemList
   where i.TAAccountID == 1
   select new Item
   {
    TAAccountID = i.TAAccountID,
    PortfolioID = i.PortfolioID,
    Shares = i.Shares,
    TradeDate = i.TradeDate,
    RunningTotal = 0
   });

found.AsParallel().ForAll(x =>
{
 var prevItems =  found.Where(i => i.PortfolioID == x.PortfolioID
  && i.TAAccountID == x.TAAccountID 
  && i.TradeDate <= x.TradeDate);
 x.RunningTotal = prevItems.Sum(s => s.Shares);
});

foreach (Item i in found)
{
 Console.WriteLine("Running total: {0}", i.RunningTotal);
}

Console.ReadLine();

如果我将找到的选择更改为.ToArray(),那么它可以正常工作,我会计算出重新计算。

任何想法我做错了什么?

1 个答案:

答案 0 :(得分:4)

执行PLINQ查询时,“找不到”IEnumerable<T>未完全执行。由于LINQ to Objects默认使用延迟执行,因此在PLINQ查询到达该位置之前,不会创建“Found”的每个元素。

由于ForAll方法在内部使用found执行,因此它将获得一个未执行或仅部分枚举的序列。通过在.ForAll调用之前添加.ToArray()(或ToList - 基本上是强制LINQ to Objects查询执行的任何操作),您将强制执行LINQ to Objects查询,这允许PLINQ查询正确执行