C# 如何在并行处理(ForEach)中正确更新或添加到集合
我试图将地址列表处理为两个集合;符合要求的地址列表;符合要求的每个地址的分数列表。 我有几个不同的标准来划分地址,但我遇到了一个错误的实现,即在并行处理期间修改集合 例如,我获取邮政编码,并为每个(+388k记录)确定Levenshtein距离是否大于或等于筛选值。如果是,则将地址添加到已编译的地址列表中。然后使用SET方法,确定地址的分数是否已经存在。如果不是,则添加。否则,请使用集合中当前的分数并更新相应的属性 我遇到了“Collection Has Modified”错误,我想不出其他方法来实现该解决方案。我正在寻找其他方法来实现这一点C# 如何在并行处理(ForEach)中正确更新或添加到集合,c#,collections,parallel-processing,thread-safety,parallel.foreach,C#,Collections,Parallel Processing,Thread Safety,Parallel.foreach,我试图将地址列表处理为两个集合;符合要求的地址列表;符合要求的每个地址的分数列表。 我有几个不同的标准来划分地址,但我遇到了一个错误的实现,即在并行处理期间修改集合 例如,我获取邮政编码,并为每个(+388k记录)确定Levenshtein距离是否大于或等于筛选值。如果是,则将地址添加到已编译的地址列表中。然后使用SET方法,确定地址的分数是否已经存在。如果不是,则添加。否则,请使用集合中当前的分数并更新相应的属性 我遇到了“Collection Has Modified”错误,我想不出其他方法
private LevenshteinDistance _ld = new LevenshteinDistance();
private int _filter_zip = int.Parse(ConfigHelper.GetAppSettingByKey("filter_zip"));
public Factory ScoreAddresses(Factory model)
{
Factory result = model;
IList<Address> _compiledList = new List<Address>();
IList<Scores> _compiledScores = new List<Scores>();
ParallelLoopResult MailLoopResult = Parallel.ForEach(
result.ALL_Addresses, factory =>
{
if (factory.MAIL_ZIP_CODE_NBR != null
&& factory.MAIL_ZIP_CODE_NBR.Length >= 1)
{
int _zipDistance = _ld.Compute(
result.Target_Address.MAIL_ZIP_CODE_NBR,
factory.MAIL_ZIP_CODE_NBR);
if (_zipDistance <= _filter_zip)
{
_compiledList.Add(factory);
Scores _score = new Scores();
_compiledScores = _score.Set(_compiledScores,
factory.INDIVIDUAL_ID, "Levenshtein_MAIL_ZIP_CODE_NBR",
_zipDistance, string.Empty, null);
}
}
});
return result;
}
public IList<Scores> Set(IList<Scores> current, int Individual_ID,
string Score_Type, int Levenshtein, string Methaphone, decimal? other)
{
int currentcount = current.Count();
bool updating = false;
IList<Scores> result = current;
try
{
Scores newscore = new Scores();
//Check if scoreing for individual already present
Scores lookingforIndv = current.AsParallel().Where(
p => p.INDIVIDUAL_ID == Individual_ID).FirstOrDefault();
if (lookingforIndv != null)
{
newscore = lookingforIndv;
updating = true;
}
else
{
newscore.INDIVIDUAL_ID = Individual_ID;
updating = false;
}
//Add score based upon indicated score type
switch (Score_Type)
{
case "Levenshtein_MAIL_ZIP_CODE_NBR":
newscore.Levenshtein_MAIL_ZIP_CODE_NBR = Levenshtein;
result.Add(newscore);
break;
//More and More Cases
}
}
catch (Exception e)
{
}
return result;
}
private LevenshteinDistance\u ld=new LevenshteinDistance();
私有int\u filter\u zip=int.Parse(ConfigHelper.GetAppSettingByKey(“filter\u zip”);
公共工厂地址(工厂模型)
{
出厂结果=型号;
IList_compiledList=新列表();
IList_compiledScores=新列表();
ParallelLoopResult MailLoopResult=Parallel.ForEach(
result.ALL_地址,工厂=>
{
如果(factory.MAIL\u ZIP\u CODE\u NBR!=空
&&factory.MAIL\u ZIP\u CODE\u NBR.Length>=1)
{
int _zipDistance=\u ld.Compute(
result.Target\u Address.MAIL\u ZIP\u CODE\u NBR,
工厂邮箱(邮政编码);
if(_zipdistancep.INDIVIDUAL_ID==INDIVIDUAL_ID).FirstOrDefault();
if(lookforindv!=null)
{
新闻核心=寻找INDV;
更新=真;
}
其他的
{
newscore.INDIVIDUAL_ID=个人_ID;
更新=假;
}
//根据指定的分数类型添加分数
开关(分数型)
{
案例“Levenshtein\u MAIL\u邮政编码\u NBR”:
newscore.Levenshtein\u MAIL\u ZIP\u CODE\u NBR=Levenshtein;
结果.添加(新闻核心);
打破
//越来越多的案例
}
}
捕获(例外e)
{
}
返回结果;
}
欢迎来到Stackoverflow。您的主题不是我的强项,但您可以通过提供[最简单的工作示例]{}来鼓励其他用户在您的问题上提供帮助。由Parallel.ForEach
调用的lambda有副作用。很难说到底发生了什么,因为您的代码非常复杂。如果您是多线程新手,我建议您从更简单的方法开始。通常,您应该避免副作用,因为它们会引入同步需求。如果你可以在一个纯LINQ查询中表达你的逻辑(没有副作用,只需输入=>输出),那么它将是安全且易于并行的。欢迎使用Stackoverflow。你的主题不是我的强项,但你可以通过提供一个[最小工作示例]{}来鼓励其他用户在你的问题上帮助你。由Parallel.ForEach
调用的lambda有副作用。很难说到底发生了什么,因为您的代码非常复杂。如果您是多线程新手,我建议您从更简单的方法开始。通常,您应该避免副作用,因为它们会引入同步需求。如果你可以在一个纯LINQ查询中表达你的逻辑(没有副作用,只需输入=>输出),那么它将是安全的,并且很容易与之并行。