C# 如何让多个线程处理相同的IEnumerable结果?

C# 如何让多个线程处理相同的IEnumerable结果?,c#,ienumerable,task,C#,Ienumerable,Task,我有一个方法,它返回一个IEnumerable,当然是用yield-return处理的。我希望有多个线程来处理这个结果,当然不需要重复它,也不需要线程安全。我将如何实现这一点 var result = GetFiles(source); for (int i = 0; i < Environment.ProcessorCount; i++) { tasks.Add(Task.Factory.StartNew(() => { ProcessCopy(result); }));

我有一个方法,它返回一个
IEnumerable
,当然是用
yield-return处理的。我希望有多个线程来处理这个结果,当然不需要重复它,也不需要线程安全。我将如何实现这一点

var result = GetFiles(source);

for (int i = 0; i < Environment.ProcessorCount; i++)
{
    tasks.Add(Task.Factory.StartNew(() => { ProcessCopy(result); }));
}

Task.WaitAll(tasks.ToArray());

您必须为每个
ProcessCopy()
调用选择一系列项-现在您正在向每个线程传递文件的完整枚举-请记住,您要传递的
IEnumerable
有一个名为
GetEnumerator()
-的方法,只有在调用该方法时(foreach在后台为您执行此操作)返回真正的枚举数,然后可以使用它逐个枚举项。由于传递的是
IEnumerable
,因此每个线程都在调用
GetEnumerator()
,从而枚举所有文件

相反,要使每个文件都具有
ProcessCopy()
处理一个文件,请执行以下操作:

foreach(string file in GetFiles(source))
{
    string fileToProcess = file;
    tasks.Add(Task.Factory.StartNew(() => { ProcessCopy(fileToProcess); }));
}

Task.WaitAll(tasks.ToArray());

我不担心处理器数量-让TPL和线程池计算出要运行多少线程才能获得最佳性能。

使用Parallel.ForEach方法可以轻松做到这一点

每个迭代都将在任务管理器中排队。当执行所有迭代时,循环将退出

var result = GetFiles(source);

Parallel.ForEach(result, current => {
    ProcessCopy(current);
});

Console.WriteLine("Done");

为什么不使用一个简单的LINQ查询来做您想要做的事情呢

var tasks =
    from f in GetFiles(source)
    select Task.Factory.StartNew(() => { ProcessCopy(f); });

Task.WaitAll(tasks.ToArray());

幕后TPL为您处理所有棘手的
环境。ProcessorCount
内容。

基本上与BrokenGlass相同,但使用我喜欢的LINQ。Parallel.ForEach似乎是迄今为止最干净的,但这绝对是我应该思考这个问题的方式。
var tasks =
    from f in GetFiles(source)
    select Task.Factory.StartNew(() => { ProcessCopy(f); });

Task.WaitAll(tasks.ToArray());