Track progress when using TPL's Parallel.ForEach

后端 未结 3 1707
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-02-07 11:36

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(Produc         


        
3条回答
  •  刺人心
    刺人心 (楼主)
    2021-02-07 11:51

    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.

提交回复
热议问题