ConcurrentDictionary and Clear()-function. Making values export threadsafe without data-loss

7.1k views Asked by At

Any ideas of making ConcurrentDictionary threadsafe in condition where values are exported to list ex, and after that dictionary is cleared. So that any other thread cannot add data between exporting and clearing.

Like this: "

List<data> list;
list = (List<data>)_changedItems.Values; //get values before clearing
_changedItems.Clear();

" And adding is done by other threads with function _changedItems.AddOrUpdate

Now there is possibility to lose new data between getting data out from the dictionary and clearing content, if some thread adds data-objects to collection before row of clearing.

Or is the only way to do adding and clearing inside lock.

lock(object)
{
    List<data> list;
    list = (List<data>)_changedItems.Values;  
    _changedItems.Clear();
}

And

lock(object)
    _changedItems.AddOrUpdate

There is need for a Clear-function that returns safely all the cleared items from dictionary..

-Larry

2

There are 2 answers

0
Tudor On

Indeed, calling two thread-safe methods in a sequence does not guarantee the atomicity of the sequence itself. You are right that a lock over both calls to get values and clear is necessary.

0
Roland Pihlakas On

You can use TryRemove(key, out value) method. It returns the removed element. This way you do not have to lock the dictionary for moving the buffered data.

List<data> list;
var keys = dict.Keys;
foreach(var key in keys)
{
    data value;
    dict.TryRemove(key, out value);
    list.Add(value);
}

Update: actually you can iterate directly over ConcurrentDictionary even while it is changing. This way you do not have to build the collection of the keys from the property .Keys, which may be (?) slow, depending on implementation.

List<data> list;
foreach(var kvp in dict)
{
    data value;
    dict.TryRemove(kvp.Key, out value);
    list.Add(value);
}