使用TPL的Parallel.ForEach时跟踪进度 [英] Track progress when using TPL's Parallel.ForEach
问题描述
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);
}});
我想将进度变量从0.0更新为1.0(当前/总计),但我不更新
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.
推荐答案
Jon的解决方案是好的,如果你需要简单的同步这个,你的第一次尝试应该总是使用 lock
。但是如果你测量锁定的速度太慢,你应该考虑使用 Interlocked
。
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
.
这种情况下,我将使用 Interlocked.Increment
增加当前计数,并将 Progress
更改为属性:
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);
}
});
此外,您可能想考虑如何处理异常,我不确定迭代结束时有异常应计为done。
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.
这篇关于使用TPL的Parallel.ForEach时跟踪进度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!