C# 从ConcurrentDictionary添加时出现错误“集合已修改;枚举操作可能无法执行”

C# 从ConcurrentDictionary添加时出现错误“集合已修改;枚举操作可能无法执行”,c#,entity-framework,concurrentdictionary,C#,Entity Framework,Concurrentdictionary,在我的代码中,我最初以ConcurrentDictionary的形式缓存实体数据项的现有对象。从并行任务中,我尝试读取预缓存的数据项。如果不存在,我想创建一个新的 ConcurrentDictionary dataEntryDict=新的ConcurrentDictionary 等待db.DataEntries .Wherede=>allObjIDs.Containsde.PAObjID .IncludeOptimizedde=>de.WorkSchedules .ToDictionaryAsy

在我的代码中,我最初以ConcurrentDictionary的形式缓存实体数据项的现有对象。从并行任务中,我尝试读取预缓存的数据项。如果不存在,我想创建一个新的

ConcurrentDictionary dataEntryDict=新的ConcurrentDictionary 等待db.DataEntries .Wherede=>allObjIDs.Containsde.PAObjID .IncludeOptimizedde=>de.WorkSchedules .ToDictionaryAsynca=>a.PAObjID,a=>a ; var allDataEntryNumbers=新的ConcurrentHashSet; 等待任务。WhenallDataEntryNumbers.Batch20.Selectasync workOrderBatch=>{ var gwoResp=等待MyServiceCall; gwoResp.dsyWorkOrder01中的每个dsyWorkOrder01TtyWorkOrder currDetail{ //获取或创建元素 DataEntry currentEntry=dataEntryDict.GetOrAdd Obj, 键=>{ var newDe=新数据项; db.DataEntries.AddnewDe;//这似乎是引发异常的行 返回纽德; } ; //设置正则字段 currentEntry.ApplytyWorkOrderUrrDetail,resourceDict; } } 如果我调用简化代码,我会从标题中得到错误消息。但并非总是如此。该方法可以从UI调用,UI在100%的情况下都能工作,但也可以从后台工作程序调用,后台工作程序每晚都会触发

这导致了以下错误:

完全导入失败,出现/InvalidOperationException。收藏是 被改进的;枚举操作不能执行

在 System.ThrowHelper.ThrowInvalidOperationExceptionExceptionResource 资源在 System.Collections.Generic.Dictionary2.ValueCollection.Enumerator.MoveNext 在 System.Data.Entity.Core.Objects.ObjectStateManager.GetEntityEntries用于检测更改Dictionary2 entityStore、列表1和条目位于 System.Data.Entity.Core.Objects.ObjectStateManager.GetEntityEntriesForDetectChanges 位于System.Data.Entity.Core.Objects.ObjectStateManager.DetectChanges 位于System.Data.Entity.Internal.InternalContext.DetectChangesBoolean 逼迫 System.Data.Entity.Internal.Linq.InternalSet1.ActionSetAction操作, EntityState新闻状态、对象实体、字符串方法名 System.Data.Entity.Internal.Linq.InternalSet1.AddObject实体 位于System.Data.Entity.DbSet1.addtenty实体位于 Namespace.Import.ImportScheduler.c__显示类9_1.b__16字符串 输入 C:\Users\reichlet\source\repos\path\Import\FullImport.cs:line 295 at System.Collections.Concurrent.ConcurrentDictionary2.GetOradTkey 键,Func2值工厂位于 Namespace.Import.ImportScheduler.c\uu DisplayClass9\u 3.d.MoveNext 在里面 C:\Users\reichlet\source\repos\path\Import\FullImport.cs:line 0 -来自引发异常的上一个位置的堆栈结束跟踪-在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw at Namespace.Import.ImportScheduler.d_u9.MoveNext 在里面 C:\Users\reichlet\source\repos\path\Import\FullImport.cs:line 323

你知道这件事出了什么问题吗

值得尝试在foreach中使用快照集合,因为在foreach操作期间可能会更改gwoResp.dsyWorkOrder01


如果这被简化了,我会讨厌维护这个代码库。我认为,如果没有一个最小的可复制的例子,这个问题是无法回答的。这能回答你的问题吗@MichaelRandall所有实际代码由1000多行组成,我甚至无法在调试环境中重现该问题。也许有人知道EF在并行添加方面存在一些问题,以及如何避免这些问题。或者我需要以某种方式锁定db.DataEntries列表吗?@LouisGo在问这个问题之前,我已经阅读了该线程。我的猜测是,另一个线程可能同时访问DbSet,这会导致一些冲突。然而,我想知道为什么只有在后台工作人员调用时才会发生这种情况。即使这样,这也是一个偶尔发生的问题。你知道这件事出了什么问题吗对当您尝试枚举集合时,该集合正在被修改,正如异常所说,以及标记的副本所解释的那样。根据您目前的笔记,您的代码中可能存在并发错误。我们无法帮助调试它,除非您提供一个可靠地再现问题的好方法。我仍然强烈怀疑这是错误。我的代码中没有任何东西可以操纵数组,它甚至不是一个列表。@AndréReichlet您的文章中没有更多的信息。这就是我发布它的原因。两天前我添加了一条带有附加信息的评论。你是说该对象是WCF服务的结果集吗。?这不能回答任何细节。或者一个最小的可复制的例子会有所帮助。问题是,我自己甚至不能复制错误。它在夜间导入时发生,但在手动触发时从不发生。我甚至试图修改我的手动触发方法以使用 计时器对象,但这也没有帮助。
foreach (dsyWorkOrder01TtyWorkOrder currDetail in gwoResp.dsyWorkOrder01) 
// following codes are ommited.
var arr = gwoResp.dsyWorkOrder01.ToArray();

foreach (dsyWorkOrder01TtyWorkOrder currDetail in arr ) 
// following codes are ommited.