Parallel.ForEach如何知道哪个项目? - 哪个循环?

时间:2013-05-01 11:19:09

标签: c# parallel.foreach

示例

  var options = new ParallelOptions()
  {
      MaxDegreeOfParallelism = 10
  };

  List<string> lstAllUrls = File.ReadAllLines("myList.txt").ToList<string>();

  Parallel.ForEach(lstAllUrls, options, myFunctionThatFetchPage);

现在这完全没问题。我想知道的是:我怎么知道我目前在哪个迭代。我的意思是说我的列表有100000个URL。它开始取出它们。但我还想在屏幕上打印当前正在获取URL的内容。

我该怎么做?如何判断循环当前在给定列表的哪个项目?

3 个答案:

答案 0 :(得分:10)

您可以使用Parallel.ForEach的以下overload

public static ParallelLoopResult ForEach<TSource>(
    IEnumerable<TSource> source,
    Action<TSource, ParallelLoopState, long> body
)

它会将当前元素索引传递给第三个参数中的委托。

答案 1 :(得分:5)

由于这些项目是并行提供给您的URL处理委托的,因此它可能会不按顺序“看到”您的列表索引,即项目将提供更高的索引,以便在索引较低的项目之前进行处理。这通常不是您想要的"M out of N"消息。

解决此问题的一种方法是在与ForEach机制分开设置的计数器上使用Interlocked.Increment

private int count;
...
void MyForEachDelegate(string urlStr) {
    ...
    int pos = Interlocked.Increment(ref count);
    if ((pos-1) % 1000 == 0) {
        Console.WriteLine("Processing URL number {0}", pos);
    }
}

答案 2 :(得分:0)

AFAIK,Parallel.ForEach就像它的表亲foreach - 不知道它在哪个迭代。您可以使用Parallel.For并使用循环变量来指示位置。一般而言,请记住,您在循环中执行的任何访问共享资源的操作都可能会降低并行度,因此请不要过度使用进度条形码等。