多线程,Linq到Sql,ConcurrentDictonary失败删除

时间:2016-05-08 20:31:42

标签: c# multithreading linq

我有一个产品属性的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);
                }

似乎拒绝删除以下Attribute元素。 enter image description here

我不明白为什么。如果我把它放在一段时间(!dic.tryRemove(ele))它将永远被卡住并且永远不会从那里移动。

线程中某处可能存在错误,但我不知道为什么。

2 个答案:

答案 0 :(得分:0)

本声明

if (!knownSpecificationBag.TryRemove(AS400SpecificationAttributeWork, out tmpstr))

将始终返回truefalse。它不会阻止。这就是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))); 
    }