0

I have a concurrentdictionary of > lets say object as Artifact.

I wanted to add a new object. The object usually contains list of keys and I have a function to get those keys.

I know how to add to the dictionary if the key doesn't exist but I am not sure how to update the List if the key is already there. Any help would be greatly appreciated

public bool AddToken(Artifact artifact)
        {
            IList<string> terms = GetTerms(artifact);
            foreach(var term in terms)
            {
                if (ExistsTerm(term))
                {
                    termDictionary.AddOrUpdate(??)
                }else
                {
                    IList<Artifact> a = new List<Artifact>();
                    a.Add(artifact); 
                    termDictionary.TryAdd(term, artifact);
                }

            }
            return true;
        }
Chit Khine
  • 830
  • 1
  • 13
  • 34
  • Would multiple threads be updating this dictionary ? or is it only one thread doing the update ? – M22an Sep 07 '16 at 04:27
  • I think only one thread – Chit Khine Sep 07 '16 at 04:30
  • Then you get `var dictArtifactList = termDictionary[];` as a list. you need a way to compare your current artifact with those in your list. My preference would be to use a LINQ query and do a `dictArtifactList.FirstOrDefault();` then update that Artifact in your list. – M22an Sep 07 '16 at 04:38
  • @mmushtaq i checked the link and it is not exactly the same but i got the idea from it. I check if my term[key].contains(artifact) and if not I just add it. – Chit Khine Sep 07 '16 at 04:48
  • ConcurrentDictionary has a totally different set of methods than Dictionary; not at all a duplicate of that linked question. – Eric Dec 18 '18 at 19:36

3 Answers3

2

Try termDictionary[<key>] = <value>. That will do both add and update (and it will prevent duplicate key exceptions (at the risk of just overwriting the existing data).

Dave V
  • 1,966
  • 9
  • 18
1

You can use AddOrUpdate.

Conceptually, the AddOrUpdate method will always result in a value change in the collection.

The point of these methods is to resolve problems with the nature of time in concurrent systems. With multiple threads, you cannot predict what elements will be found in the collection at any point of execution.

Here is MSDN Example

class CD_GetOrAddOrUpdate
{
    // Demonstrates:
    //      ConcurrentDictionary<TKey, TValue>.AddOrUpdate()
    //      ConcurrentDictionary<TKey, TValue>.GetOrAdd()
    //      ConcurrentDictionary<TKey, TValue>[]
    static void Main()
    {
        // Construct a ConcurrentDictionary
        ConcurrentDictionary<int, int> cd = new ConcurrentDictionary<int, int>();

        // Bombard the ConcurrentDictionary with 10000 competing AddOrUpdates
        Parallel.For(0, 10000, i =>
        {
            // Initial call will set cd[1] = 1.  
            // Ensuing calls will set cd[1] = cd[1] + 1
            cd.AddOrUpdate(1, 1, (key, oldValue) => oldValue + 1);
        });

        Console.WriteLine("After 10000 AddOrUpdates, cd[1] = {0}, should be 10000", cd[1]);

        // Should return 100, as key 2 is not yet in the dictionary
        int value = cd.GetOrAdd(2, (key) => 100);
        Console.WriteLine("After initial GetOrAdd, cd[2] = {0} (should be 100)", value);

        // Should return 100, as key 2 is already set to that value
        value = cd.GetOrAdd(2, 10000);
        Console.WriteLine("After second GetOrAdd, cd[2] = {0} (should be 100)", value);
    }
}
Kaushik
  • 2,072
  • 1
  • 23
  • 31
0

ConcurrentDictionary GetOrAdd method get a factory delegate:

var list = termDictionary.GetOrAdd(term, t=>new List<Artifact>());
list.Add(artifact);
Inbar Barkai
  • 282
  • 1
  • 3
  • 12