c# - 使用 TPL 的 Parallel.ForEach 时跟踪进度

标签 c# multithreading c#-4.0 task-parallel-library plinq

跟踪以下进度的最佳方式是什么

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(当前/总计),但我不想使用任何会对并行性产生不利影响的东西。

最佳答案

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

此外,您可能想考虑如何处理异常,我不确定以异常结束的迭代是否应该算作已完成。

关于c# - 使用 TPL 的 Parallel.ForEach 时跟踪进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14536656/

相关文章:

c# - 如何从 xsd 创建 wsdl

c# - HTML 标签如何转换为 HtmlControl?

c - 如何将参数从线程传递到c中的函数

com - 做COM时是否需要在C#4中调用Marshal.ReleaseComObject?

c#-4.0 - 尝试使用 POST,但 API 尝试使用 GET

c# - MySQL 在字符串前面添加空格

java - 为什么 Future isDone() 会像 Future get() 一样阻塞程序?

c# - ThreadPool 给出了惊人的结果,我这样做对吗? (不,我没有)

c# - 重启任务还是创建新任务?

c# - 套接字在第一次接收后停止