简体   繁体   中英

Parallel.ForEach on List<Object> Thread Safety

As far as Thread Safety goes is this ok to do or do I need to be using a different collection ?

        List<FileMemberEntity> fileInfo = getList(); 

        Parallel.ForEach(fileInfo, fileMember =>
        {
              //Modify each fileMember 
        }

As long as you are only modifying the contents of the item that is passed to the method, there is no locking needed.

(Provided of course that there are no duplicate reference in the list, ie two references to the same FileMemberEntity instance.)

If you need to modify the list itself, create a copy that you can iterate, and use a lock when you modify the list:

List<FileMemberEntity> fileInfo = getList();

List<FileMemberEntity> copy = new List<FileMemberEntity>(fileInfo);
object sync = new Object();

Parallel.ForEach(copy, fileMember => {
  // do something
  lock (sync) {
    // here you can add or remove items from the fileInfo list
  }
  // do something
});

You're safe since you are just reading. Just don't modify the list while you are iterating over its items.

We should use less lock object to make it faster. Only lock object in different local threads of Parrallel.ForEach:

List<FileMemberEntity> copy = new List<FileMemberEntity>(fileInfo);
object sync = new Object();

Parallel.ForEach<FileMemberEntity, List<FileMemberEntity>>(
      copy,
      () => { return new List<FileMemberEntity>(); },
      (itemInCopy, state, localList) =>
      {
         // here you can add or remove items from the fileInfo list
         localList.Add(itemInCopy);
         return localList;
      },
      (finalResult) => { lock (sync) copy.AddRange(finalResult); }
); 

 // do something

Reference: http://msdn.microsoft.com/en-gb/library/ff963547.aspx

If it does not matter what order the FileMemberEntity objects are acted on, you can use List<T> because you are not modifying the list.

If you must ensure some sort of ordering, you can use OrderablePartitioner<T> as a base class and implement an appropriate partitioning scheme. For example, if the FileMemberEntity has some sort of categorization and you must process each of the categories in some specific order, you would want to go this route.

Hypothetically if you have

Object 1 Category A

Object 2 Category A

Object 3 Category B

there is no guarantee that Object 2 Category A will be processed before Object 3 Category B is processed when iterating a List<T> using Parallel.ForEach .

The MSDN documentation you link to provides an example of how to do that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM