I am trying to learn usage of Parallel.ForEach
loop with partitioning. I encounter a code and try to modify it but getting error.
See one example code:
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; }
}
}
I tried to change the above code to create new List<T>
instance from localInit
section of Parallel.ForEach
and from body
populate List<T>
with data and from localFinally
return the new List<T>
but facing problem.
List<Person> persons1 = new List<Person>();
Parallel.ForEach(persons, new Person(), drow =>
{
},
(persons1) => lock{}
);
Please help me to do it. I want to populate a list from Parallel.ForEach
with data from another list. I want to create a local List<T>
which I like to populate with data from my global List<T>
. How it will be possible? How can I declare a local list with in Parallel.ForEach
localInit
section?
from body
section I want to populate that local list with data from global List<T>
and from localFinally
block that want to return my local List<T>
to outside. Please guide me to achieve this.
As an exercise you can do something like this:
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);
}
}
);
This should not be used in production code though. What you should do usually depends on actual task you want to perform.