使用TPL的Parallel.ForEach时跟踪进度 [英] Track progress when using TPL's Parallel.ForEach

查看:159
本文介绍了使用TPL的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆