Track progress when using TPL's Parallel.ForEach
c#, c#-4.0, multithreading, plinq, task-parallel-library
Solution
Jon's solution is good, if you need simple synchronization like this, your first attempt should almost always use `lock`. But if you measure that the locking slows things too much, you should think about using something like `Interlocked`.
In this case, I would use `Interlocked.Increment` to increment the current count, and change `Progress` into a property:
private long total;
private long current;
public double Progress
{
get
{
if (total == 0)
return 0;
return (double)current / total;
}
}
…
this.total = Products.LongCount();
this.current = 0;
Parallel.ForEach(Products, product =>
{
try
{
var price = GetPrice(SystemAccount, product);
SavePrice(product, price);
}
finally
{
Interlocked.Increment(ref this.current);
}
});
Also, you might want to consider what to do with exceptions, I'm not sure that iterations that ended with an exception should be counted as done.
Problem
What is the best way way to track progress in the following ``` long total = Products.LongCount(); long current = 0; double Progress = 0.0; Parallel.ForEach(Products, product => { try { var price = GetPrice(SystemAccount, product); SavePrice(product,price); } finally { Interlocked.Decrement(ref this.current); }}); ``` I want to update the progress variable from 0.0 to 1.0 (current/total) but i don't want to use anything that would have an adverse effect on the parallelism.