这是我的密码:
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);这个地方总是会发生的:System.IndexOutOfRangeException
我已经将Paralle.Foreach更改为Parallel.For,并将foreach更改为for,但没有任何更改。我必须使用并行,因为学生计数大约100000,如果我只使用foreach替换Parallel.Foreach,它将花费160+秒,如果锁定place.....still slow......if使用Parallel.Foreach,它将使用20秒左右,但我不能处理异常。
我已经试过用这个替换它了:
StudentNames name = STUDENT_NAMES.Where(x => x.SearchWords == tempWords).FirstOrDefault();
if (null != name)
name.student.Add(StudentModel);但这个问题有时还是会发生的.如果我只是try...catch它并忽略它,那么当我稍后访问STUDENT_NAMES列表时,它仍然抛出这个异常.
我也试过用ConcurrentBag<>,但是速度很慢.我受不了.
有什么好办法处理吗?非常感谢!
更新:
我不明白的是:为什么我不能在Parallel.Foreach的列表中添加一些东西。我认为Parallel.Foreach会使用很多线程,但是事件使用多线程添加没有任何问题。
线程1添加和线程2添加没有任何关系.为什么会有这样的例外?
发布于 2014-07-08 20:56:54
List不适合从多个线程访问。这样做是不安全的。您可能会遇到各种各样的问题,从索引异常,添加丢失,复制,其他类型的错误,实际上几乎任何事情。
我也试过用ConcurrentBag<>,但是速度很慢.我受不了.
当这两个选项中只有一个真正有效时,性能就无关紧要了。您可以拥有正确工作的代码,并且所需时间尽可能长,或者您可以拥有无法工作的代码,而这与它做错的速度无关。
当然,你还有其他的选择,比如重新设计你的程序,以使用一种固有的更有效的算法,而不是试图做一些效率很低的事情,而只是通过并行来掩盖这一事实。您目前正在列表中执行线性搜索,以便为另一个集合中的每个项查找匹配项,这是一个非常糟糕的设计;您应该使用一个可以更有效地搜索的集合,例如HashSet。然而,如果不知道问题的细节,我们就不可能说出应用程序的正确设计应该是什么。
https://stackoverflow.com/questions/24641425
复制相似问题