197

我有点困惑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

4

6 回答 6

299

Foreach 循环:

  • 迭代是按顺序进行的,一个接一个
  • foreach 循环从单个线程运行。
  • 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();
        }
    }
}

输出

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
于 2013-07-05T09:54:51.200 回答
136
string[] lines = File.ReadAllLines(txtProxyListPath.Text);
List<string> list_lines = new List<string>(lines);
Parallel.ForEach(list_lines, line =>
{
    //Your stuff
});
于 2012-09-03T17:18:11.257 回答
44
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
});

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

于 2012-09-03T17:17:53.113 回答
11

对于大文件,请使用以下代码(您的内存消耗较少)

Parallel.ForEach(File.ReadLines(txtProxyListPath.Text), line => {
    //Your stuff
});
于 2016-04-06T15:09:20.143 回答
4

这些线条对我有用。

string[] lines = File.ReadAllLines(txtProxyListPath.Text);
var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 10 };
Parallel.ForEach(lines , options, (item) =>
{
 //My Stuff
});
于 2019-08-01T08:07:59.627 回答
1

我想补充一下并行选项。如果您没有提到它,默认情况下所有 RAM 都将用于此,这可能会给您在生产中带来问题。所以最好在代码中添加最大并行度。

Parallel.ForEach(list_lines, new ParallelOptions { MaxDegreeOfParallelism = 2 }, line =>
{
    
});
于 2021-06-03T08:09:08.877 回答