Parallel.ForEach与Task.Run和Task.WhenAll
使用Parallel.ForEach或Task.Run()asynchronous启动一组任务之间有什么区别?
版本1:
List<string> strings = new List<string> { "s1", "s2", "s3" }; Parallel.ForEach(strings, s => { DoSomething(s); }); 版本2:
 List<string> strings = new List<string> { "s1", "s2", "s3" }; List<Task> Tasks = new List<Task>(); foreach (var s in strings) { Tasks.Add(Task.Run(() => DoSomething(s))); } await Task.WhenAll(Tasks); 
	
在这种情况下,第二种方法将asynchronous等待任务完成而不是阻塞。
 但是,在Task.Run中使用Task.Run有一个缺点 – 使用Parallel.ForEach ,会创build一个Partitioner ,以避免执行更多的任务。  Task.Run将始终为每个项目执行单个任务(因为您正在执行此操作),但Parallel类批处理工作,因此您创build的任务less于总工作项目。 这可以提供明显更好的整体性能,尤其是在循环体每个项目有less量工作的情况下。 
如果是这种情况,你可以写两个选项:
 await Task.Run(() => Parallel.ForEach(strings, s => { DoSomething(s); })); 
请注意,这也可以写在这个简短的forms:
 await Task.Run(() => Parallel.ForEach(strings, DoSomething)); 
 第一个版本将同步阻塞调用线程(并运行一些任务)。 
 如果它是一个UI线程,这将冻结用户界面。 
第二个版本将在线程池中asynchronous运行任务,并释放调用线程,直到完成。
调度algorithm也有差异。
请注意,你的第二个例子可以缩短为
 await Task.WhenAll(strings.Select(s => Task.Run(() => DoSomething(s)));