我最近需要在报告上执行总计。对于每个组,我按行排序,然后根据组中的先前行计算运行总计。啊哈!我想,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()
,那么它可以正常工作,我会计算出重新计算。
任何想法我做错了什么?
答案 0 :(得分:4)
执行PLINQ查询时,“找不到”IEnumerable<T>
未完全执行。由于LINQ to Objects默认使用延迟执行,因此在PLINQ查询到达该位置之前,不会创建“Found”的每个元素。
由于ForAll方法在内部使用found执行,因此它将获得一个未执行或仅部分枚举的序列。通过在.ForAll调用之前添加.ToArray()(或ToList - 基本上是强制LINQ to Objects查询执行的任何操作),您将强制执行LINQ to Objects查询,这允许PLINQ查询正确执行