我有一个需要同时处理的文件列表。我尝试使用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。在这种情况下,这可能太重了,不值得(获得索引既好又轻)。我之所以提到它,是因为"我能在并行任务之间零共享的情况下做到这一点吗?"这个问题应该一直被考虑,即使后来被驳回。