26

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 
        }

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

4

4 回答 4

34

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, i.e. 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
});
于 2012-06-27T18:10:13.507 回答
9

你是安全的,因为你只是在阅读。只是在迭代其项目时​​不要修改列表。

于 2012-06-27T17:52:17.077 回答
3

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

于 2014-11-26T10:59:14.090 回答
1

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.

于 2012-06-27T17:54:13.947 回答