ParallelQuery.ForAll方法中的增量ID



我有一个需要同时处理的文件列表。我尝试使用ParallelQuery类的ForAll扩展方法。我没有按顺序处理文件,所以我使用了ForAll。

这是我的示例代码:

List<FileInfo> files = GetFilesToProcess();
files.AsParallel().ForAll(f => { // Process file here });

它工作得很好,但现在我需要为每个文件生成一个唯一的整数ID,如果不将AsParallel.ForAll更改为ForEach,我不知道如何做到这一点。

我在某个地方读到了我需要作为一个Interlocked,但仍然会有一个问题。

希望你能在这里给我一个主意。

谢谢!

您可以使用Interlocked.Increment生成ID,也可以直接使用索引:

List<FileInfo> files = GetFilesToProcess();
files.AsParallel().Select((f, i) => new {File=f, ID=i})
     .ForAll(fp => 
           {
              FileInfo file = fp.File;
              int id = fp.ID; // ID is the index in the list
              // Process file here
           });

如果你想使用Interlocked.Increment,你可以做:

List<FileInfo> files = GetFilesToProcess();
int globalId = -1;
files.AsParallel().ForAll(f => 
                         { 
                              // Process file here 
                              int id = Interlocked.Increment(ref globalId);
                              // use ID
                         });

话虽如此,如果你的整个目标是在一个集合上做"工作",我建议你把它写成Parallel.For或Parallel.ForEach。这一点要清楚得多,因为你使用LINQ风格的语法并不是为了产生副作用:

List<FileInfo> files = GetFilesToProcess();
Parallel.For(0, files.Count, i =>
{
    var file = files[i];
    // Use i and file as needed
});

如果您真的必须这样做,那么您可以通过Interlocked.Increment处理一个int

使用源的索引是更好的选择,因为这是已经从分割器获得的信息,即使是Interlocked给出的光共享,仍然是共享的。

或者,您可以跳过它,使用某种UUID。在这种情况下,这可能太重了,不值得(获得索引既好又轻)。我之所以提到它,是因为"我能在并行任务之间零共享的情况下做到这一点吗?"这个问题应该一直被考虑,即使后来被驳回。

相关内容

  • 没有找到相关文章

最新更新