使用TPL的Parallel.ForEach时,跟踪进度(Track progress when u

2019-08-08 08:15发布

什么是最好的方式方法来跟踪在以下方面取得

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(电流/个),但我不希望使用任何会对并行性产生不利影响。

Answer 1:

乔恩的解决方案是好的,如果你需要这样简单的同步,你的第一次尝试应该总是用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);
    }
});

此外,你可能要考虑如何处理例外做,我不知道这与一个异常结束迭代应该做计算。



Answer 2:

因为你只是在做几个简单的计算,确保原子通过锁定一个合适的对象上:

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;
        }
    }});


Answer 3:

不使用在身体的任何阻挡A液:

long total = Products.LongCount();
BlockingCollection<MyState> states = new BlockingCollection<MyState>();

Parallel.ForEach(Products, () =>
{
    MyState myState = new MyState();
    states.Add(myState);
    return myState;
},
(i, state, arg3, myState) =>
{
    try
    {
        var price = GetPrice(SystemAccount, product);
        SavePrice(product,price);
    }
    finally
    {
        myState.value++;
        return myState;
    }
},
i => { }
);

然后,访问目前进展:

(float)states.Sum(state => state.value) / total


文章来源: Track progress when using TPL's Parallel.ForEach