平行的.每个人怎么知道在哪个项目?-哪个循环

本文关键字:项目 循环 每个人 | 更新日期: 2023-09-27 18:11:34

示例

  var options = new ParallelOptions()
  {
      MaxDegreeOfParallelism = 10
  };
  List<string> lstAllUrls = File.ReadAllLines("myList.txt").ToList<string>();
  Parallel.ForEach(lstAllUrls, options, myFunctionThatFetchPage);

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

我该怎么做呢?我如何知道当前循环在给定列表的哪一项?

平行的.每个人怎么知道在哪个项目?-哪个循环

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

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

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

由于项目是并行提供给您的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);
    }
}

很好,平行。ForEach就像它的表兄ForEach——不擅长知道它在哪个迭代。你可以用Parallel。而使用循环变量来告诉位置。通常要记住,在循环中访问共享资源的任何操作都可能降低并行度,所以不要过度使用进度条或类似的代码。