Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在ConcurrentDictionary.GetOrAdd中使用lock语句时的已知副作用?_C#_Entity Framework_Concurrentdictionary - Fatal编程技术网

C# 在ConcurrentDictionary.GetOrAdd中使用lock语句时的已知副作用?

C# 在ConcurrentDictionary.GetOrAdd中使用lock语句时的已知副作用?,c#,entity-framework,concurrentdictionary,C#,Entity Framework,Concurrentdictionary,从ConcurrentDictionaryValueFactory方法中的多个线程添加到实体框架DbSet时,我遇到了一些问题。我试图通过引入lock语句来消除这个问题。不过,这似乎有一些奇怪的副作用。在一些罕见和随机的情况下,我的代码会抛出一个KeyNotFoundException,即使编程应该防止这种情况发生。我想我监督了一些事情 使用(ESBClient client=new ESBClient()){//WCF服务 client.Open(); //限制并行请求的最大数量 var-es

ConcurrentDictionary
ValueFactory
方法中的多个线程添加到实体框架
DbSet
时,我遇到了一些问题。我试图通过引入
lock
语句来消除这个问题。不过,这似乎有一些奇怪的副作用。在一些罕见和随机的情况下,我的代码会抛出一个
KeyNotFoundException
,即使编程应该防止这种情况发生。我想我监督了一些事情

使用(ESBClient client=new ESBClient()){//WCF服务
client.Open();
//限制并行请求的最大数量
var-esbLimiter=新信号量slim(4);
ConcurrentDictionary dataEntryDict=新的ConcurrentDictionary(
等待db.DataEntries
.Where(de=>allObjIDs.Contains(de.PAObjID))
.IncludeOptimized(de=>de.WorkSchedules)
.ToDictionaryAsync(a=>a.PAObjID,a=>a)
);
//获取每个数据输入编号的WorkOrderDataSet02
等待Task.WhenAll(allDataEntryNumbers.Batch(20)。选择(async workOrderBatch=>{
等待esbLimiter.WaitAsync();
Debug.WriteLine($“在{s.elapsedmillesons}之后使用并行{esbLimiter.CurrentCount}启动新批处理”;
试一试{
int-retryCounter=0;
getWorkOrderDataSet02Response gwoResp;
retryCurrentWorkOrderDataSetResp:
试一试{
gwoResp=await client.getWorkOrderDataSet02Async(
新getWorkOrderDataSet02Request(
"?",
companyGroup.Key,
string.Join(“,”,workOrderBatch.Select(wob=>wob.DataEntryNumber)),
“WNTREIB”,
"?",
“行动,销售”,
“D”
)
);
}捕获(System.ServiceModel.CommunicationException ex){
//在最终崩溃之前,最多重试3次
if(retryCounter++<3){
等待HandleServiceRetryError(“getWorkOrderDataSet02Async”,retryCounter,s.ElapsedMilliseconds,ex);
转到RetryCurrentWorkordataSetResp;
}否则
投掷;
}
//迭代ESB返回的所有工单
foreach(gwoResp.dsyWorkOrder01中的DSYWORKORDER01TTYWORKORDERCurrDetail){//dsyWorkOrder01是一个对象数组。它来自WCF调用。PAObjID是唯一的。
//获取或创建元素
DataEntry currentEntry=dataEntryDict.GetOrAdd(
Obj,
键=>{
DataEntry newDe=新的DataEntry();
lock(db.DataEntries){//我介绍了那些lock语句
db.DataEntries.Add(newDe);//这是一开始就有问题的行
}
返回纽德;
}
);
//设置正则字段
currentEntry.ApplyTyWorkOrder(currDetail,resourceDict);//此方法应用PAObjID属性
}
//删除服务不再提供的所有元素
锁(db.DataEntries){
训练台
.Where(wob=>!gwoResp.dsyWorkOrder01
.Where(wo=>wo.DataEntryNumber.HasValue)
.选择(wo=>wo.DataEntryNumber.Value)
.Contains(wob.DataEntryNumber)
)
.ToArray()
.ForEach(数据项=>{
试一试{
db.DataEntries.Remove(dataEntryDict[dataEntry.ObjID]);//此行抛出KeyNotFoundException
}捕获(例外情况除外){
抛出新异常($“Key{dataEntry.ObjID}不在列表中。”,ex);
}
});
}
//更新进度
进度报告(.1f+总步长*联锁增量(参考当前步长)*.8f);
}最后{
Debug.WriteLine($“在{s.elapsedmillesons}之后使用并行{esbLimiter.CurrentCount}完成批处理”;
esbLimiter.Release();
}
}));
}
//下面是应用方法
public void applytyworkorder(dsyWorkOrder01TtyWorkOrder src,Dictionary resourceDict){
删除=假;
DataEntryNumber=src.DataEntryNumber.Value;
PAObjID=src.Obj;//此处应用PAObjID
IsHeader=src.IsHeader;
件数=转换为16(src.生产数量);
PartNo=src.Article;
作业编号=src.WorkOrder;
StartDate=src.StartDate;
FinishDate=src.EndDate;
FinishedPA=src.WorkOrderStatus==“R”;
//更新方法
UpdateFromTtyCustomer(src.ttyCustomer?.FirstOrDefault());
UpdateFromPart(src.ttyPart?.FirstOrDefault());
UpdateFromSalesDocHeader(src.ttysalestocHeader?.FirstOrDefault());
更新工作时间表(src.ttyWorkOrderActivity,resourceDict);
}
<>我对每一行都加了大写注释。 我不知道为什么会发生这种错误。根据我的理解,我只尝试从
dataEntryDict
dictionary
dataEntry.ObjID
键中获取一个条目,我以前在循环的同一次迭代中添加了这些键

在我介绍这两个lock语句之前,标有“THIS IS the line THAT problemble at FIRST PLACE”的行偶尔抛出一个异常:“Collection WAS modified;enumeration operation may not execute.”在深入研究EF的代码之后,我意识到这应该与
DbSet.Add
方法的实现方式有关

使用
锁时是否有任何已知的副作用
lock (db.DataEntries) { // I INTRODUCED THOSE LOCK STATEMENTS
    db.DataEntries.Add(newDe); // THIS IS THE LINE THAT WAS PROBLEMATIC IN THE FIRST PLACE
}