C# while循环中的字典和删除字典中的项
我有一个字典,如果字典中的项目经过所有处理,我想删除它C# while循环中的字典和删除字典中的项,c#,C#,我有一个字典,如果字典中的项目经过所有处理,我想删除它 var dictEnum = dictObj.GetEnumerator(); while (dictEnum.MoveNext()) { Parallel.ForEach(dictObj, pOpt, (KVP, loopState) => { pro
var dictEnum = dictObj.GetEnumerator();
while (dictEnum.MoveNext())
{
Parallel.ForEach(dictObj, pOpt, (KVP, loopState) =>
{
processAndRemove(KVP.Key);
});
}
private void processAndRemove(string keyId)
{
try
{
<does stuff>
dictObj.Remove(keyId);
} catch(exception ex) {
...
<does not remove anything, wants to retry until it doesn't fail>
}
}
var dictEnum=dictObj.GetEnumerator();
while(dictEnum.MoveNext())
{
Parallel.ForEach(dictObj,pOpt,(KVP,loopState)=>
{
processAndRemove(KVP.Key);
});
}
私有void processAndRemove(字符串keyId)
{
尝试
{
dictObj.Remove(keyId);
}捕获(例外情况除外){
...
如果同时对集合进行迭代,则无法从集合中删除该项。
但是,您可以将要删除的所有元素存储在单独的集合中
然后,当您完成枚举后,可以迭代列表以从原始集合中删除每个项
或者,也可以去看看。它很漂亮。用户@JaredPar提供的公认答案摘录是:
foreach ( var s in MyCollection.Where(p => p.Value.Member == foo).ToList() ) {
MyCollection.Remove(s.Key);
}
我不认为你可以用字典来做这件事。相反,你可以做一些像dictionary.Values.ToList()
,去掉你想要的,然后调和差异
这个问题有更多关于它的信息开始第二个集合,并向其中添加您想要保留的值。正如Jalayn所说,您不能在枚举集合时从集合中删除。您必须重写代码,以便将其添加到另一个集合中,然后枚举该集合并从原始集合中删除项目收藏
比如:
var toRemove = new Dictionary<int, string>() //whatever type it is
Parallel.ForEach(dictObj, pOpt, (KVP, loopState) =>
{
toRemove.Add(KVP);
});
foreach (var item in toRemove)
{
dictObject.Remove(item.Key);
}
var toRemove=new Dictionary()//不管它是什么类型
Parallel.ForEach(dictObj,pOpt,(KVP,loopState)=>
{
toRemove.Add(KVP);
});
foreach(toRemove中的var项目)
{
dictObject.Remove(item.Key);
}
为什么要显式调用GetEnumerator()
而不是使用foreach
?有foreach
语句可以帮助您。在这种情况下,您在循环中使用MoveNext()
,但从不读取Current
属性
看起来您试图在dictObj
上使用Parallel.ForEach
,但您确定它是线程安全的类型吗?可能不是。它的类型是什么
最后,错误文本不言而喻。您不能修改正在迭代的同一个集合。来自我的对话:Jeppe Stig Nielsen产生了一个想法,尝试使用ConcurrentDictionary
这是我的测试代码,在这里我可以从字典中删除项目(从Parallel.Foreach循环中),而循环将继续,直到计数==0或retryAttempts>5
public static ConcurrentDictionary<string, myRule> ccDict= new ConcurrentDictionary<string, myRule>();
try
{
while (ccDict.Count > 0)
{
Parallel.ForEach(ccDict, pOptions, (KVP, loopState) =>
{
//This is the flag that tells the loop do exit out of loop if a cancellation has been requested
pOptions.CancellationToken.ThrowIfCancellationRequested();
processRule(KVP.Key, KVP.Value, loopState);
}); //End of Parallel.ForEach loop
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
Console.ReadLine();
}
public static int processRule(string rId, myRule rule, ParallelLoopState loopState)
{
try
{
if (rId == "001" || rId == "002")
{
if (rId == "001" && ccDict[rId].RetryAttempts == 2)
{
operationPassed(rId);
return 0;
}
operationFailed(rId);
}
else
{
operationPassed(rId);
}
return 0;
}
catch (Exception ex)
{
Console.WriteLine("failed : " + ex.Message.ToString());
return -99;
}
}
private static void operationPassed(string rId)
{
//Normal Operation
ccDict[rId].RulePassed = true;
ccDict[rId].ExceptionMessage = "";
ccDict[rId].ReturnCode = 0;
Console.WriteLine("passed: " + rId + " Retry Attempts : " + ccDict[rId].RetryAttempts.ToString());
rule value;
ccDict.TryRemove(rId, out value);
}
private static void operationFailed(string ruleId)
{
//This acts as if an EXCEPTION has OCCURED
int retryCount = 0;
ccDict[rId].RulePassed = false;
ccDict[rId].RetryAttempts = ccDict[rId].RetryAttempts + 1;
ccDict[rId].ExceptionMessage = "Forced Fail";
ccDict[rId].ReturnCode = -99;
ccDict.TryUpdate(rId, ccDict[rId], ccDict[rId]);
if (ccDict[rId].RetryAttempts >= 5)
{
Console.WriteLine("Failed: " + rId + " Retry Attempts : " + ccDict[rId].RetryAttempts.ToString() + " : " + ccDict[rId].ExceptionMessage.ToString());
cancelToken.Cancel();
}
}
public class myRule
{
public Boolean RulePassed = true;
public string ExceptionMessage = "";
public int RetryAttempts = 0;
public int ReturnCode = 0;
public myRule()
{
RulePassed = false;
ExceptionMessage = "";
RetryAttempts = 0;
ReturnCode = 0;
}
}
公共静态ConcurrentDictionary ccDict=新ConcurrentDictionary();
尝试
{
而(ccDict.Count>0)
{
Parallel.ForEach(ccDict,pOptions,(KVP,loopState)=>
{
//这是一个标志,它告诉循环如果已请求取消,就退出循环
pOptions.CancellationToken.ThrowIfCancellationRequested();
processRule(KVP.Key、KVP.Value、loopState);
});//Parallel.ForEach循环的结束
}
}
捕获(例外情况除外)
{
Console.WriteLine(例如Message.ToString());
Console.ReadLine();
}
公共静态int processRule(字符串rId、myRule规则、ParallelLoopState loopState)
{
尝试
{
如果(rId==“001”| | rId==“002”)
{
如果(rId==“001”&&ccDict[rId].RetryAttempts==2)
{
操作通过(rId);
返回0;
}
操作失败(rId);
}
其他的
{
操作通过(rId);
}
返回0;
}
捕获(例外情况除外)
{
Console.WriteLine(“失败:+ex.Message.ToString());
返回-99;
}
}
私有静态无效操作已通过(字符串rId)
{
//正常运行
ccDict[rId].RulePassed=true;
ccDict[rId]。例外消息=”;
ccDict[rId].ReturnCode=0;
WriteLine(“传递:“+rId+”重试尝试:“+ccDict[rId].RetryAttempts.ToString());
规则值;
ccDict.TryRemove(rId,out值);
}
私有静态无效操作失败(字符串规则ID)
{
//这就像发生了异常一样
int retryCount=0;
ccDict[rId].RulePassed=false;
ccDict[rId].RetryAttempts=ccDict[rId].RetryAttempts+1;
ccDict[rId].ExceptionMessage=“强制失败”;
ccDict[rId].ReturnCode=-99;
ccDict.TryUpdate(rId,ccDict[rId],ccDict[rId]);
如果(ccDict[rId].RetryAttempts>=5)
{
Console.WriteLine(“失败:“+rId+”重试尝试:“+ccDict[rId].RetryAttempts.ToString()+”:“+ccDict[rId].ExceptionMessage.ToString());
cancelToken.Cancel();
}
}
公共类myRule
{
public Boolean RulePassed=true;
公共字符串例外消息=”;
公共整数重试次数=0;
public int ReturnCode=0;
公共规则()
{
RulePassed=false;
例外消息=”;
重试次数=0;
ReturnCode=0;
}
}
根据我的研究,在执行while循环时,您需要字典中有一个枚举器。我正在探索while循环的用法,以便它能够继续运行所有失败的项,而不必启动另一个进程。@JeffVdictObj
字段的类型是什么?@JeffV如果这意味着System.Collection