首页 > 解决方案 > C#如何填充和返回列表从 Parallel.ForEach 使用分区

问题描述

我正在尝试学习 Parallel.Foreach 循环与分区的用法。我遇到代码并尝试对其进行修改,但出现错误。

查看一个示例代码

 namespace TaskPartitionExample
 {
     public partial class Form1 : Form
     {
         public Form1()
         {
             InitializeComponent();
         }
    
         private void button1_Click(object sender, EventArgs e)
         {
             List<Person> persons = GetPerson();
             int ageTotal = 0;
    
             Parallel.ForEach
             (
                 persons,
                 () => 0,
                 (person, loopState, subtotal) => subtotal + person.Age,
                 (subtotal) => Interlocked.Add(ref ageTotal, subtotal)
             );
    
             MessageBox.Show(ageTotal.ToString());
         }
    
         static List<Person> GetPerson()
         {
             List<Person> p = new List<Person>
             {
                 new Person() { Id = 0, Name = "Artur", Age = 5 },
                 new Person() { Id = 1, Name = "Edward", Age = 10 },
                 new Person() { Id = 2, Name = "Krzysiek", Age = 20 },
                 new Person() { Id = 3, Name = "Piotr", Age = 15 },
                 new Person() { Id = 4, Name = "Adam", Age = 10 }
             };
    
             return p;
         }
     }
    
     class Person
     {
         public int Id { get; set; }
         public string Name { get; set; }
         public int Age { get; set; }
     }
 }

我尝试更改上面的代码以从Parallel.Foreach的init部分创建新的 List 实例,并从主体填充 List 数据,并从LocalFinally返回新列表但面临问题。

         List<Person> persons1=new List<Person>();
         Parallel.ForEach(persons,new Person(), drow =>
             {

             },
             (persons1)=> lock{}
         );

请帮我做。我想用另一个列表中的数据填充parellel.foreach中的列表。我想创建一个本地列表,我喜欢用我的全局列表中的数据填充它。怎么可能?我如何声明一个本地列表 inparallel.foreach init 部分? 从正文部分,我想用来自全局列表和最终块的数据填充该本地列表,这些数据想要将我的本地列表返回到外部。请指导我实现这一目标。

谢谢

标签: c#parallel.foreach

解决方案


作为练习,您可以执行以下操作:

var persons1 = new List<Person>();
var locker = new object();
Parallel.ForEach(
    persons,
    () => new List<Person>(), // initialize aggregate per thread 
    (person, loopState, subtotal) =>
    {
        subtotal.Add(person); // add current thread element to aggregate 
        return subtotal; // return current thread aggregate
    },
    p => // action to combine all threads results
    {
        lock (locker) // lock, cause List<T> is not a thread safe collection
        {
            persons1.AddRange(p);
        }
    }
);

但是,这不应该在生产代码中使用。您应该做什么通常取决于您要执行的实际任务。


推荐阅读