Try the code below.
class Test
{
public static void Add(ref long total, long finalResult) { total = finalResult; }
static void Main()
{
int[] nums = Enumerable.Range(0, 1000000).ToArray();
long total = 0;
// First type parameter is the type of the source elements
// Second type parameter is the type of the local data (subtotal)
Parallel.ForEach<int, long>(nums, // source collection
() => 0, // method to initialize the local variable
(j, loop, subtotal) => // method invoked by the loop on each iteration
{
subtotal += nums[j]; //modify local variable
return subtotal; // value to be passed to next iteration
},
// Method to be executed when all loops have completed.
// finalResult is the final value of subtotal. supplied by the ForEach method.
(finalResult) => Add(ref total, finalResult)
);
Console.WriteLine("The total from Parallel.ForEach is {0}", total);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
Run multiple times. What happen to the result?
class Test
{
static void Main()
{
int[] nums = Enumerable.Range(0, 1000000).ToArray();
long total = 0;
// First type parameter is the type of the source elements
// Second type parameter is the type of the local data (subtotal)
Parallel.ForEach<int, long>(nums, // source collection
() => 0, // method to initialize the local variable
(j, loop, subtotal) => // method invoked by the loop on each iteration
{
subtotal += nums[j]; //modify local variable
return subtotal; // value to be passed to next iteration
},
// Method to be executed when all loops have completed.
// finalResult is the final value of subtotal. supplied by the ForEach method.
(finalResult) => Interlocked.Add(ref total, finalResult)
);
Console.WriteLine("The total from Parallel.ForEach is {0}", total);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
}
It is obvious that you cannot get the consistent result because of parallelism is not linear. Hence the Interlocked.Add is needed to get the result all the time.