Mad*_*kor 11 c# multithreading plinq task-parallel-library c#-4.0
以下是跟踪进度的最佳方法
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);
}});
Run Code Online (Sandbox Code Playgroud)
我想将进度变量从0.0更新为1.0(当前/总)但我不想使用会对并行性产生负面影响的任何内容.
Jon的解决方案很好,如果您需要这样的简单同步,您的第一次尝试应该几乎总是使用lock.但是,如果你测量锁定减慢了太多的东西,你应该考虑使用类似的东西Interlocked.
在这种情况下,我将使用Interlocked.Increment增加当前计数,并更改Progress为属性:
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);
}
});
Run Code Online (Sandbox Code Playgroud)
此外,您可能想要考虑如何处理异常,我不确定以异常结束的迭代应该计为完成.
由于您只是进行一些快速计算,因此通过锁定适当的对象来确保原子性:
long total = Products.LongCount();
long current = 0;
double Progress = 0.0;
var lockTarget = new object();
Parallel.ForEach(Products, product =>
{
try
{
var price = GetPrice(SystemAccount, product);
SavePrice(product,price);
}
finally
{
lock (lockTarget) {
Progress = ++this.current / total;
}
}});
Run Code Online (Sandbox Code Playgroud)