2016-05-08 5 views
0

私は、製品のConcurrentDictionary of Attributesを持っています。これらの属性には、製品IDと、属性の名前と、属性に含まれるオプションの値があります。私はこのConcurrentDictionaryを持っています。なぜなら、属性名で辞書内の各属性を処理するために作成されたスレッドがあるからです。マルチスレッド、Linq to Sql、ConcurrentDictonaryが失敗します。

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); 
       } 

次のような属性要素は削除されないようです。 enter image description here

なぜか分かりません。私はしばらく(!dic.tryRemove(ele))それを置く場合、それは永遠に立ち往生し、決してそこから移動しません。

スレッド内のどこかにエラーがあるかもしれませんが、理由はわかりません。

+0

私は全体の文脈を見ることができない使用している場合 - 項目が辞書になかった場合は何が起こるかを2つのスレッドが両方とも同じコードを実行した場合、そのうちの1つがそれを削除し、他のスレッドはそこに存在しませんでしたか? –

答えて

0

適切な等号とGetHashCodeメソッドを実装しTryRemove

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))); 
    } 
0

この文

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

常にtrueまたはfalseを返します。ブロックされません。それはConcurrentDictionaryの動作です。キーが辞書にない場合はfalseを返します。

このメソッドがfalseを返している間にループしていると、ループが開始されたときに項目が辞書にないことを意味します。どちらかが辞書になかったか、別のスレッドが既にそれを削除したかのいずれかです。

辞書にはでなくになるまでループするつもりですか?
あなたはこれを試みることができる:

if (!knownSpecificationBag.TryRemove(AS400SpecificationAttributeWork, out tmpstr) 
    && !knownSpecificationBag.ContainsKey(AS400SpecificationAttributeWork)) 
+0

'TryRemove()'と 'ContainsKey()'の呼び出しの間に足りない項目を追加することはできませんでしたか?これだけレースをさらに進めてくれるのではないですか? –

+0

私はFirstorDefaultがその1つのオブジェクトを返していると思うし、TryRemoveは失敗を続け、同じ要素をループし続けます。 –

関連する問題