C# 如何使用分区从 Parallel.ForEach 填充和 return List<T>
C# How to populate and return List<T> from Parallel.ForEach using partitioning
我正在尝试学习 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 实例包含数据的列表和来自 LocalFinally return 的新列表但面临问题。
List<Person> persons1=new List<Person>();
Parallel.ForEach(persons,new Person(), drow =>
{
},
(persons1)=> lock{}
);
请帮我做一下。我想用另一个列表中的数据填充 parellel.foreach 中的列表。我想创建一个本地列表,我想用我的全局列表中的数据填充它。这怎么可能?我如何在 parallel.foreach 初始化部分声明一个 本地列表?
从正文部分我想用来自全局列表的数据填充该本地列表,并从想要 return 我的本地列表到外部的最终块。请指导我实现这一目标。
谢谢
作为练习,您可以这样做:
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);
}
}
);
虽然这不应该在生产代码中使用。您应该做什么通常取决于您要执行的实际任务。
我正在尝试学习 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 实例包含数据的列表和来自 LocalFinally return 的新列表但面临问题。
List<Person> persons1=new List<Person>();
Parallel.ForEach(persons,new Person(), drow =>
{
},
(persons1)=> lock{}
);
请帮我做一下。我想用另一个列表中的数据填充 parellel.foreach 中的列表。我想创建一个本地列表,我想用我的全局列表中的数据填充它。这怎么可能?我如何在 parallel.foreach 初始化部分声明一个 本地列表? 从正文部分我想用来自全局列表的数据填充该本地列表,并从想要 return 我的本地列表到外部的最终块。请指导我实现这一目标。
谢谢
作为练习,您可以这样做:
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);
}
}
);
虽然这不应该在生产代码中使用。您应该做什么通常取决于您要执行的实际任务。