我有一个产品属性的ConcurrentDictionary。这些属性具有属性名称的产品ID和值以及属性具有的任何选项。我有这个ConcurrentDictionary,因为我创建了一些线程,用于按属性名称处理字典中的每个属性。
if (knownAttribute.AttributeType.Value.Equals("Product Specification"))
{
Console.WriteLine("Started a thread for: " + knownAttribute.AttributeTypeId + ", " + knownAttribute.Value);
while (true)
{
/* if (AS400SpecificationAttributes.IsEmpty && knownSpecificationBag.IsEmpty && gatherRowsTasks.All(x => x.IsCompleted))
break;*/
AS400SpecificationAttribute AS400SpecificationAttributeWork = null;
AS400SpecificationAttributeWork = knownSpecificationBag.Keys.FirstOrDefault(x => x.AttributeName == knownAttribute.Value);
if (AS400SpecificationAttributeWork != null)
{
var product = ctx.Products.FirstOrDefault(x => x.ProductNumber == AS400SpecificationAttributeWork.ProductNumber);
if (product == null)
continue;
var productAttribute = new ProductAttribute();
productAttribute.Attribute = knownAttribute;
if (AS400SpecificationAttributeWork.AttributeValue != null)
{
var knownAttributeOption = ctx.AttributeOptions.FirstOrDefault(x => x.Attribute.Equals(knownAttribute) && x.Value.Equals(AS400SpecificationAttributeWork.AttributeValue));
if (knownAttributeOption == null)
{
knownAttributeOption = new AttributeOption();
knownAttributeOption.Value = AS400SpecificationAttributeWork.AttributeValue;
knownAttributeOption.Attribute = knownAttribute;
ctx.AttributeOptions.InsertOnSubmit(knownAttributeOption);
ctx.SubmitChanges();
}
productAttribute.AttributeOption = knownAttributeOption;
productAttribute.AttributeOptionId = knownAttributeOption.Id;
}
product.ProductAttributes.Add(productAttribute);
ctx.SubmitChanges();
string tmpstr = null;
if (!knownSpecificationBag.TryRemove(AS400SpecificationAttributeWork, out tmpstr))
Thread.Sleep(50);
}
else
{
if (tryCounter < 5)
{
tryCounter++;
Thread.Sleep(1000);
Console.WriteLine("Thread waiting for work: Product Specification:" + knownAttribute.Value);
continue;
}
else
{
int outVal;
threadTracker.TryRemove("Product Specification:" + knownAttribute.Value, out outVal);
Console.WriteLine("Closing Thread: Product Specification:" + knownAttribute.Value);
break;
}
}
Thread.Sleep(50);
}
我不明白为什么。如果我把它放在一段时间(!dic.tryRemove(ele))它将永远被卡住并且永远不会从那里移动。
线程中某处可能存在错误,但我不知道为什么。
答案 0 :(得分:0)
本声明
if (!knownSpecificationBag.TryRemove(AS400SpecificationAttributeWork, out tmpstr))
将始终返回true
或false
。它不会阻止。这就是ConcurrentDictionary
的行为。如果密钥不在字典中,它将返回false
。
如果你在循环时该方法返回false并且它被卡住了,这意味着当循环开始时该项不在字典中。要么它从未在字典中,要么另一个线程已经删除它。
你是否打算循环直到字典中不的项目为止? 你可以试试这个:
if (!knownSpecificationBag.TryRemove(AS400SpecificationAttributeWork, out tmpstr)
&& !knownSpecificationBag.ContainsKey(AS400SpecificationAttributeWork))
答案 1 :(得分:0)
使用TryRemove时实现正确的equals和gethashcode
public override int GetHashCode()
{
return new { this.name, this.value, this.group, this.productNumber }.GetHashCode();
}
public bool Equals(AS400SpecificationAttribute other)
{
if (other == null)
return false;
return (this.ProductNumber.Equals(other.productNumber) && ((this.group != null && this.group.Equals(other.AttributeGroup)) || (this.group == null && other.AttributeGroup == null)) && ((this.name!= null && this.name.Equals(other.AttributeName)) || (this.name == null && other.AttributeName == null)) && ((this.value != null && this.value.ToUpper().Equals(other.AttributeValue.ToUpper())) || (this.value == null && other.AttributeValue == null)));
}