2

例子

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

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

  Parallel.ForEach(lstAllUrls, options, myFunctionThatFetchPage);

现在这工作得很好。我想知道的是:我如何知道我目前处于哪个迭代中。我的意思是说我的列表有 100000 个 URL。它开始获取它们。但我也想在屏幕上打印目前正在获取的 URL。

我怎样才能做到这一点?如何判断当前循环在给定列表的哪一项?

4

3 回答 3

11

您可以使用以下重载Parallel.ForEach

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

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

于 2013-05-01T11:21:14.920 回答
5

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

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

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);
    }
}
于 2013-05-01T11:27:16.230 回答
0

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

于 2013-05-01T11:33:07.393 回答