Search code examples
c#dictionaryconcurrencythread-safety

I need to mimic a ConcurrentDictionary with a normal Dictionary in C#


Just as I said in the title I need to mimic a ConcurrentDictionary using Dictionaries because I need to serialize the said collection and the concurrent variant is not serializable. Any Idea in how ConcurrentDictionary handles multi-threading and how I should implement it?

I haven't tried it yet, i feel like a fish out of water.


Solution

  • BinaryFormatter serialization is considered obsolete. Try using Json serialization instead:

    ConcurrentDictionary<string, Variant> dict = new ConcurrentDictionary<string, Variant>();
    dict.TryAdd("one", new Variant() { Name = "one", Coordinate = new System.Drawing.Point() { } });
    dict.TryAdd("two", new Variant() { Name = "two", Coordinate = new System.Drawing.Point() { } });    
    var serialized = JsonConvert.SerializeObject(dict);
    
    //This works just fine
    var deserialized = JsonConvert.DeserializeObject<ConcurrentDictionary<string, Variant>>(serialized);
    

    You can then save this string in the storage of your choice. Your data structures are not known so I just made something up for illustration purposes.

    The one thing you will have to worry about is locking the serialization methods as you are attempting to do this several times per second. If you are saving it to disk, you are likely to run into file lock issues and what not. For this reason, you should reconsider your state saving strategy as well.

    Something along the lines of:

    private ConcurrentDictionary<string, Variant> _history = new ConcurrentDictionary<string, Variant>();
    
    //Somewhere in your code you populate the dictionary
    _history.TryAdd("one", new Variant() { Name = "one", Coordinate = new System.Drawing.Point() { } });
    _history.TryAdd("two", new Variant() { Name = "two", Coordinate = new System.Drawing.Point() { } });
    
    private object _lock = new object();
    private void SaveHistory()
    {
        lock (_lock)
        {
            var serialized = JsonConvert.SerializeObject(_history);
            DataLayer.SaveHistory(serialized);
        }                       
    }
    
    private void RestoreHistory()
    {
        lock (_lock)
        {
            var serialized = DataLayer.GetHistory();
            _history = JsonConvert.DeserializeObject<ConcurrentDictionary<string, Variant>>(serialized);
        }
    }