Using PLINQ to calculate and update values within the enclosure does not work
- by Keith
I recently needed to do a running total on a report. Where for each group, I order the rows and then calculate the running total based on the previous rows within the group. Aha! I thought, a perfect use case for PLINQ!
However, when I wrote up the code, I got some strange behavior. The values I was modifying showed as being modified when stepping through the debugger, but when they were accessed they were always zero.
Sample Code:
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();
If I change the select for found to be .ToArray(), then it works fine and I get calculated reuslts.
Any ideas what I am doing wrong?