何时使用Parallel.ForEach循环而不是常规的foreach?
我对Parallel.ForEach
有些困惑。
什么是Parallel.ForEach
,它究竟干什么?
请不要参考任何MSDN链接。
这是一个简单的例子:
string[] lines = File.ReadAllLines(txtProxyListPath.Text); List<string> list_lines = new List<string>(lines); foreach (string line in list_lines) { //My Stuff }
我如何用Parallel.ForEach
重写这个例子?
string[] lines = File.ReadAllLines(txtProxyListPath.Text); List<string> list_lines = new List<string>(lines); Parallel.ForEach(list_lines, line => { //Your stuff });
Foreach循环:
- 迭代依次进行,一个接一个
- foreach循环从单个线程运行。
- foreach循环在.NET的每个框架中定义
- 慢进程的执行可能会比较慢 ,因为它们是连续运行的
- 进程2不能启动,直到1完成。 进程3不能启动,直到2&1完成…
- 执行快速stream程可以更快 ,因为没有线程开销
Parallel.ForEach:
- 执行以并行的方式进行。
- Parallel.ForEach使用多个线程。
- Parallel.ForEach在.NET 4.0及以上框架中定义。
- 慢进程的执行可以更快 ,因为它们可以并行运行
- 进程1,2和3 可以同时运行(参见下面例子中的重用线程)
- 由于额外的线程开销,执行快速进程可能会变慢
下面的例子清楚地表明了传统的foreach循环和
Parallel.ForEach()示例
using System; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namespace ParallelForEachExample { class Program { static void Main() { string[] colors = { "1. Red", "2. Green", "3. Blue", "4. Yellow", "5. White", "6. Black", "7. Violet", "8. Brown", "9. Orange", "10. Pink" }; Console.WriteLine("Traditional foreach loop\n"); //start the stopwatch for "for" loop var sw = Stopwatch.StartNew(); foreach (string color in colors) { Console.WriteLine("{0}, Thread Id= {1}", color, Thread.CurrentThread.ManagedThreadId); Thread.Sleep(10); } Console.WriteLine("foreach loop execution time = {0} seconds\n", sw.Elapsed.TotalSeconds); Console.WriteLine("Using Parallel.ForEach"); //start the stopwatch for "Parallel.ForEach" sw = Stopwatch.StartNew(); Parallel.ForEach(colors, color => { Console.WriteLine("{0}, Thread Id= {1}", color, Thread.CurrentThread.ManagedThreadId); Thread.Sleep(10); } ); Console.WriteLine("Parallel.ForEach() execution time = {0} seconds", sw.Elapsed.TotalSeconds); Console.Read(); } } }
产量
Traditional foreach loop 1. Red, Thread Id= 10 2. Green, Thread Id= 10 3. Blue, Thread Id= 10 4. Yellow, Thread Id= 10 5. White, Thread Id= 10 6. Black, Thread Id= 10 7. Violet, Thread Id= 10 8. Brown, Thread Id= 10 9. Orange, Thread Id= 10 10. Pink, Thread Id= 10 foreach loop execution time = 0.1054376 seconds
使用Parallel.ForEach示例
1. Red, Thread Id= 10 3. Blue, Thread Id= 11 4. Yellow, Thread Id= 11 2. Green, Thread Id= 10 5. White, Thread Id= 12 7. Violet, Thread Id= 14 9. Orange, Thread Id= 13 6. Black, Thread Id= 11 8. Brown, Thread Id= 10 10. Pink, Thread Id= 12 Parallel.ForEach() execution time = 0.055976 seconds
string[] lines = File.ReadAllLines(txtProxyListPath.Text); // No need for the list // List<string> list_lines = new List<string>(lines); Parallel.ForEach(lines, line => { //My Stuff });
这将导致线路在循环内并行parsing。 如果你想要一个更详细的,更less的“引用导向”的Parallel类的介绍,我写了一个关于TPL的系列文章,其中包括一个关于Parallel.ForEach的章节 。
对于大文件使用下面的代码(你less了内存饿)
Parallel.ForEach(File.ReadLines(txtProxyListPath.Text), line => { //Your stuff });