2

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

这是我的示例代码:

List<FileInfo> files = GetFilesToProcess();

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

它工作得很好,但现在我需要为每个文件生成一个唯一的整数 ID,我不确定如何在不将 AsParallel.ForAll 更改为 ForEach 的情况下执行此操作。

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

希望你能在这里给我一个想法。

谢谢!

4

2 回答 2

3

您可以使用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
});
于 2012-08-28T00:12:26.737 回答
0

如果你真的必须,那么你可以int通过Interlocked.Increment.

使用源索引是一个更好的选择,因为这是分区器已经提供的信息,即使是Interlocked给定的光共享,仍然是共享的。

或者,您可以跳过它并使用某种 UUID。在这种情况下,这可能是值得的(获得索引既好又轻)。我之所以提到它,是因为“我可以在并行任务之间零共享的情况下做到这一点吗?” 应始终考虑,即使以后被解雇。

于 2012-08-28T00:14:36.003 回答