如何将此foreach代码转换为Parallel.ForEach?

Sil*_*ght 174 c# multithreading .net-4.0 parallel.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
}
Run Code Online (Sandbox Code Playgroud)

我该如何重写这个例子Parallel.ForEach

Jig*_*Raj 265

Foreach循环:

  • 迭代按顺序进行,逐个进行
  • foreach循环从单个Thread运行.
  • foreach循环在.NET的每个框架中定义
  • 进程的执行速度可能较慢,因为它们是串行运行的
    • 过程2在1完成之前无法启动.流程3在2和1完成之前无法启动...
  • 快速进程的执行可以更快,因为没有线程开销

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

产量

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
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)

  • 我真的不同意你的说法,即Parallel.ForEach(总是)更快.这实际上取决于循环内操作的沉重程度.这可能是也可能不值得引入并列论的开销. (61认同)
  • @stenly我认为睡眠正是它是_good_例子的原因.你不会使用快速单次迭代的PFE(正如Martao所解释的那样) - 因此这个答案使得迭代变慢,并且突出了PFE的(正确)优势.我同意,虽然这需要在答案中解释,但大胆的"总是更快"是非常误导的. (7认同)
  • @Jignesh这甚至不是很好的测量示例所以我根本不会参考这个.删除"Thread.Sleep(10);" 从每个循环体中再次尝试. (3认同)

L.B*_*L.B 118

string[] lines = File.ReadAllLines(txtProxyListPath.Text);
List<string> list_lines = new List<string>(lines);
Parallel.ForEach(list_lines, line =>
{
    //Your stuff
});
Run Code Online (Sandbox Code Playgroud)

  • 我很困惑,这个答案被标记为正确的答案,因为没有解释原始帖子的问题"什么是Parallel.ForEach以及它到底做了什么?"...... (116认同)
  • 只是想指出它(更多的是OP),所以没有误导的想法它只适用于`List <T>`;) (6认同)
  • @fosb问题是标题被编辑以完全改变含义......所以这个答案不再有任何意义.话虽如此,它仍然是一个糟糕的答案 (6认同)

Ree*_*sey 43

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
});
Run Code Online (Sandbox Code Playgroud)

这将导致在循环内并行解析行.如果你想要一个更详细,更少"面向参考"的Parallel类介绍,我写了一个关于TPL的系列,其中包括一个关于Parallel.ForEach部分.


小智 8

对于大文件使用以下代码(你的内存较少)

Parallel.ForEach(File.ReadLines(txtProxyListPath.Text), line => {
    //Your stuff
});
Run Code Online (Sandbox Code Playgroud)


Pri*_*sad 5

这些行对我有用。

string[] lines = File.ReadAllLines(txtProxyListPath.Text);
var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 10 };
Parallel.ForEach(lines , options, (item) =>
{
 //My Stuff
});
Run Code Online (Sandbox Code Playgroud)