0

Suppose I have a "distinct" list of Persons that I need to update. I would like to use Parallel.For()

method in question:

public void UpdatePerson(Person row){
   row.Name = //get from cache and update property
}

VS

public Person UpdatePerson(Person row){
   row.Name = //get from cache and update property
   return row;
}

When using Parallel.For() to enumerate this list and run these updates in parallel (ie. calling this method), is there any potential problems with using one vs the other?

ShaneKm
  • 20,823
  • 43
  • 167
  • 296
  • 1
    You need to show the code that calls `UpdatePerson` also is `//get from cache and update property` thread safe? Can it be used concurrently from multiple threads without issues? Lastly, if the `Name` property is not a auto-implmented property you need to show us that too. – Scott Chamberlain Oct 03 '16 at 21:32
  • Cache implementation is not thread safe.. however for the purpose of this discussion suppose I've written to cache prior to executing Parallel.for and no changes will be written meanwhile does that matter? Reading from cache based on unique identifier and (knowing that all persons in the list are distinct) does it matter? Since one Task will get a value for id 1..another id 2 and so on (at the same time but different ids) – ShaneKm Oct 03 '16 at 22:29

1 Answers1

3

Let's leave for a moment the parallel part, what you want to do is some opertaion on items in a list of persons, would you choose to use for this purpose for loop:

for(int i = 0; i < persons.Length, i++)
{
    persons[i].Name = "SomeName;
}

Or foreach loop:

foreach(Person person in persons)
{
    person.Name = "SomeName";
}

I prefer to use the foreach loop in this case because I find it much more suitable and clear, in my opnion that is an obvious choice.

Now lets come back to the parallel part, Parallel.For() should be used to execute for loops in parallel while Parallel.Foreach() should be used to execute foreach loops in parallel.
So if we agreed that foreach loop was more appropriate in this case then we should also prefer Parallel.Foreach() over Parallel.For().

Now for your question Parallel.Foreach() will take an Action of T as an argument, so if you want to pass a method name to the operation it must be void method since Action of T is a delegate to a void method that gets one parameter of type T.

So using your first approach should work:

public void UpdatePersonName(Person person)
{
    person.Name = "SomeName";
}

And the parallel part (using this overload):

Parallel.Foreach(persons, UpdatePersonName);

Another option instead of creating seprate methods is to use lambda expressions:

Parallel.Foreach(persons, person => person.Name = "SomeName" );

For this reasons you can't use your second method:

public Person UpdatePersonName(Person person)
{
   person.Name = "SomeName";
   return person;
}

Inside Parallel.Foreach() because it's return type is not void.

Another importatnt thing you should know, if you are using Parallel.Foreach() you will need to ensure thread safety and most of the times you will need to use some kind of locking to achieve that.
You should consider this carefuly because sometimes it does not worth the overhead, in some cases foreach loops can run faster than their parallel equivalents.

Community
  • 1
  • 1
YuvShap
  • 3,825
  • 2
  • 10
  • 24