我最近需要对报告进行汇总。对于每个组,我对行进行排序,然后根据组内之前的行计算运行总计。啊哈!我想,这是 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();
如果我将 find 的选择更改为 .ToArray()
,那么它工作正常,并且我会得到计算结果。
知道我做错了什么吗?
最佳答案
当您的 PLINQ 查询执行时,“找到”IEnumerable<T>
尚未完全执行。由于 LINQ to Objects 默认情况下使用延迟执行,因此在 PLINQ 查询到达该位置之前,不会创建“Found”的每个元素。
由于 ForAll 方法在内部使用 find 执行,因此它会得到一个未执行的或仅部分枚举的序列。通过在 .ForAll 调用之前添加 .ToArray() (或 ToList - 基本上是强制执行 LINQ to Objects 查询的任何内容),您将强制执行 LINQ to Objects 查询,从而允许 PLINQ 查询正确执行.
关于c# - 使用 PLINQ 计算和更新机箱内的值不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2789672/