LockableDictionary
LockableDictionary<Key, Value> wraps another dictionary into read-only lockable dictionary.
// Create dictionary
IDictionary<string, string> map = new Dictionary<string, string>
{
{ "Key1", "Value1" },
{ "Key2", "Value2" },
};
// Wraps into lockable dictionary
var wrapedMap = new LockableDictionary<string, string>(map);
LockableDictionary.Create(keyType, valueType, internalDictionary) creates dictionary using type arguments.
LockableDictionary<string, string> map =
(LockableDictionary<string, string>)
LockableDictionary.Create(typeof(string), typeof(string));
LockableDictionary<Key, Value> creates wrapper and internal map.
// Create map
var map = new LockableDictionary<string, string>
{
{ "Key1", "Value1" },
{ "Key2", "Value2" },
};
.SetReadOnly() extension method of IReadOnly locks dictionary.
// Lock
map.SetReadOnly();
After locking write throws InvalidOperationException.
// Write
try
{
map["Key3"] = "Value3";
}
catch (InvalidOperationException)
{
}
LockableDictionaryRecord<Key, Value> is a record object dictionary that can be locked into read-only.
// Create map
var map = new LockableDictionaryRecord<string, string>
{
{ "Key1", "Value1" },
{ "Key2", "Value2" },
};
If internal dictionary of LockableDictionary is not internally synchronized, then it must be externally locked with its .SyncRoot in concurrent use.
// Create internal map
var internalMap = new Dictionary<int, int>();
// Create map
var map = new LockableDictionary<int, int>(internalMap);
// Is underlying map internally synchronized
WriteLine(map.IsSynchronized); // False
// Run 50 tasks in parallel.
Parallel.For(0, 50,
(int i) => { lock (map.SyncRoot) map[i % 5] = i; }
);
// Print values
foreach (var kv in map) WriteLine($"{kv.Key}={string.Join(',', kv.Value)}");
// 0 = 15
// 1 = 6
// 3 = 8
// 2 = 2
// 4 = 4
When internal dictionary is internally synchronized, then values can be added concurrently without lock.
// Create internal map
var internalMap = new ConcurrentDictionary<int, int>();
// Create map
var map = new LockableDictionary<int, int>(internalMap);
// Is underlying map internally synchronized
WriteLine(map.IsSynchronized); // true
// Run 50 tasks in parallel.
Parallel.For(0, 50, (int i) => map[i % 5] = i);
// Print values
foreach (var kv in map) WriteLine($"{kv.Key}={string.Join(',', kv.Value)}");
// 0 = 30
// 1 = 31
// 2 = 32
// 3 = 43
// 4 = 29
Full Example
Full example
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using Avalanche.Utilities;
using static System.Console;
public class lockabledictionary
{
public static void Run()
{
{
// <01>
// Create dictionary
IDictionary<string, string> map = new Dictionary<string, string>
{
{ "Key1", "Value1" },
{ "Key2", "Value2" },
};
// Wraps into lockable dictionary
var wrapedMap = new LockableDictionary<string, string>(map);
// </01>
}
{
// <02>
LockableDictionary<string, string> map =
(LockableDictionary<string, string>)
LockableDictionary.Create(typeof(string), typeof(string));
// </02>
map["A"] = "B";
}
{
// <03>
// Create map
var map = new LockableDictionary<string, string>
{
{ "Key1", "Value1" },
{ "Key2", "Value2" },
};
// </03>
// <04>
// Lock
map.SetReadOnly();
// </04>
// <05>
// Write
try
{
map["Key3"] = "Value3";
}
catch (InvalidOperationException)
{
}
// </05>
}
{
// <10>
// Create map
var map = new LockableDictionaryRecord<string, string>
{
{ "Key1", "Value1" },
{ "Key2", "Value2" },
};
// </10>
}
{
// <11>
// Create internal map
var internalMap = new Dictionary<int, int>();
// Create map
var map = new LockableDictionary<int, int>(internalMap);
// Is underlying map internally synchronized
WriteLine(map.IsSynchronized); // False
// Run 50 tasks in parallel.
Parallel.For(0, 50,
(int i) => { lock (map.SyncRoot) map[i % 5] = i; }
);
// Print values
foreach (var kv in map) WriteLine($"{kv.Key}={string.Join(',', kv.Value)}");
// 0 = 15
// 1 = 6
// 3 = 8
// 2 = 2
// 4 = 4
// </11>
}
{
// <12>
// Create internal map
var internalMap = new ConcurrentDictionary<int, int>();
// Create map
var map = new LockableDictionary<int, int>(internalMap);
// Is underlying map internally synchronized
WriteLine(map.IsSynchronized); // true
// Run 50 tasks in parallel.
Parallel.For(0, 50, (int i) => map[i % 5] = i);
// Print values
foreach (var kv in map) WriteLine($"{kv.Key}={string.Join(',', kv.Value)}");
// 0 = 30
// 1 = 31
// 2 = 32
// 3 = 43
// 4 = 29
// </12>
}
}
}