4

I have a concurrent dictionary which I am using it to do some thread-safe functionalities.

For example I have the following code :

var  myConcurrenctDictionary= new ConcurrentDictionary<int,int>();
if (myConcurrenctDictionary.TryAdd(personId, personId) == false)
{
    throw new Exception("");
}

But now I need a thread-safe way to try adding multiple values to the concurrent dictionary at once, which returns false and not inserting any values of the specified ids if it fails.

So, could you please guide me to how I can implement that?

Simple Code
  • 2,354
  • 2
  • 27
  • 56
  • What should happen if thread 1 adds multiple entries and thread 2 adds one of the entries? – vc 74 Mar 05 '18 at 07:06
  • I want to fail and not adding any entry of that thread(something like transactions all entries succeed or all fail) – Simple Code Mar 05 '18 at 07:08
  • 1
    Then you probably need to lock during insertions which defeats the use of a concurrent dictionary a little bit – vc 74 Mar 05 '18 at 07:10
  • 1
    `ConcurrentDictionary` cannot (is not designed to) do that, so you have to resort to regular locking. – Evk Mar 05 '18 at 07:12

2 Answers2

1

The ConcurrentDictionary<TKey, TValue> type exposes GetOrAdd method for adding a non-existing key to the dictionary in a thread-safe manner. It seems you're looking for a way to bulk add multiple items at once. Assuming you indeed need exactly that functionality, there is no easy way to achieve that. Unfortunately, the ConcurrentDictionary doesn't expose its internal locking mechanism to the children (nothing protected). So your best bet would be to implement a new CustomConcurrentDictionary, based on the simple Dictionary<K, V> type, rather than ConcurrentDictionary<K, V>. You can use this code as a reference.

Artak
  • 2,819
  • 20
  • 31
  • 2
    Even if you could access the locking mechanism, `ConcurrentDictionary<,>` only locks one of its hash buckets at a time. So if you are adding several entries (that may end up in different buckets) you could have a pretty hard time trying to leverage the framework code. – John Wu Mar 05 '18 at 07:21
  • Agree, that's why I just referred to that code as a reference, not to be used is as is and add the method on top. – Artak Mar 05 '18 at 07:29
1

You can create a ConcurrentDictionary, data and all, by passing an IEnumerable to the constructor. So, to add a series of entries, you could do this:

    var combined = new ConcurrentDictionary<string,string>
    (
        original.Concat(additional)
    );
    original = combined;

Unfortunately this won't help you much if some other thread is modifying the original dictionary, so you'd have to implement an additional locking mechanism surrounding the reference. In the end, you'd probably be better off making your own class (as in Artak's answer).

John Wu
  • 50,556
  • 8
  • 44
  • 80