简体   繁体   中英

Why I can't use List.Add() on Parallel.For or Parallel.Foreach?

This is my code :

Parallel.ForEach(Students, item =>
{
   StudentModel studentModel = new StudentModel(item);

   // Maybe he/she has alot of name
   foreach (var words in studentModel.StudentNames.Split(','))
   {
        if (string.IsNullOrWhiteSpace(words))
                return;

        string tempWords = words.Trim();
        // add it to student names list
        STUDENT_NAMES.Where(x => x.SearchWords == tempWords).FirstOrDefault().student.Add(studentModel);


     }
     // add it to student list
     STUDENT_MODELS.Add(studentModel);
});

What I want to do is, I get the student list. convert it to student model, get student names(because one student has a lot names), then I add the names to names list, that's because maybe later I need get same name students and do some thing..... finally add student to student models list.

The problem happening on :

STUDENT_NAMES.Where(x => x.SearchWords == tempWords).FirstOrDefault().student.Add(studentModel);

This place always happening : System.IndexOutOfRangeException

I already change the Paralle.Foreach to Parallel.For , and change the foreach to for, but there is nothing changed. I must use Parallel because the students count about 100000, if I just use foreach replace Parallel.Foreach, it will take 160+ second, If I lock that place.....still slow......if use Parallel.Foreach, it will use 20 second around, but I can't handle the exception.

I already try use this replace it:

StudentNames name = STUDENT_NAMES.Where(x => x.SearchWords == tempWords).FirstOrDefault();
if (null != name)
   name.student.Add(StudentModel);

But the problem still happening on some times........ if I just try...catch it and ignore it, then When I later access the STUDENT_NAMES list , it still throw that exception............

I also try use ConcurrentBag<> , but the speed very slow....I can't take it.....

Is there any good way to handle it please. Thank you very much!

UPDATE:

What I can't understand is: Why I can't add some thing to the list in the Parallel.Foreach. I think Parallel.Foreach will use a lot thread , but event use multiple thread add is not any problem with it.

thread 1 add and thread 2 add not any relationship.... Why there is happening that exception?

List is not designed to be accessed from multiple threads. it is not safe to do so. You can run into all sorts of problems, ranging from out of index exceptions, additions being lost, duplicated, other types of errors, really just about anything.

I also try use ConcurrentBag<> , but the speed very slow....I can't take it.....

Performance is irrelevant when only one of the two options actually works. You can have code that works correctly and takes as long as that takes, or you can have code that doesn't work, and to which how fast it does the wrong this is irrelevant.

Of course you have other options, such as looking at ways of redesigning your program to use an inherently more effective algorithm instead of trying to do something really inefficient and just parallelism it to hide that fact. The fact that you're currently performing a liner search on your list to find a matching item for each item in another collection is a rather poor design; you should use a collection that can be more efficiently searched, such as a HashSet . Without knowing the details of the problem though, we couldn't possibly say what the proper design of the application should be.

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