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.