为什么我不能在并行上使用List.Add()For或Parallel.Foreach

本文关键字:Add For Foreach Parallel List 不能 并行 为什么 | 更新日期: 2023-09-27 18:11:58

这是我的代码:

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);
});

我想做的是,我得到学生名单。将其转换为学生模型,获取学生姓名(因为一个学生有很多姓名),然后将姓名添加到姓名列表,这是因为以后我可能需要获取相同姓名的学生并做一些事情.....最后将学生添加到学生模型列表中。

问题发生在:

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

这个地方总是发生:系统。IndexOutOfRangeException

我已经改变了并行。Foreach to Parallel。为之,而变为为之,却什么也没变。我必须用Parallel,因为学生数大约是100000,如果我用foreach代替Parallel。对于每个,它将花费160+秒,如果我锁定那个地方.....还慢……如果使用Parallel。对于每个,它将使用20秒左右,但我无法处理异常。

我已经试过用这个代替它了:

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

但问题仍然发生在某些时候........如果我试着…捕获它并忽略它,然后当我稍后访问STUDENT_NAMES列表时,它仍然抛出异常............

我也尝试使用ConcurrentBag<>,但是速度很慢....我不能接受.....

请问有什么好的处理方法吗?非常感谢!

更新:

我不能理解的是:为什么我不能在Parallel.Foreach中添加一些东西到列表中。我认为是平行的。Foreach会使用很多线程,但是event使用多个线程add没有任何问题。

线程1添加和线程2添加没有任何关系....为什么会出现这个异常?

为什么我不能在并行上使用List.Add()For或Parallel.Foreach

List不是设计为多线程访问。这样做不安全。您可能会遇到各种各样的问题,从索引异常、添加项丢失、重复、其他类型的错误,实际上是任何事情。

我也尝试使用ConcurrentBag<>,但速度很慢....我不能接受.....

当两个选项中只有一个有效时,

性能无关紧要。你可以有正常工作的代码,花费的时间和它花费的时间一样长,也可以有不能工作的代码,这与它出错的速度有多快无关。

当然,你还有其他的选择,比如重新设计你的程序,使用一个本质上更有效的算法,而不是试图做一些非常低效的事情,只是并行化它来隐藏这个事实。事实上,你目前在列表上执行线性搜索,为另一个集合中的每个项目找到匹配的项目,这是一个相当糟糕的设计;您应该使用可以更有效地搜索的集合,例如HashSet。在不知道问题的细节的情况下,我们不可能说出应用程序的正确设计应该是什么。