I need some directions here.
I have the following key/value cache:
public class Cache<TKey, TValue> : ICache<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> _internalCache;
private readonly object _syncLock = new object();
public Cache()
{
_internalCache = new Dictionary<TKey, TValue>();
}
public TValue this[TKey key]
{
get
{
lock (_syncLock) {
//...
}
}
set
{
lock (_syncLock) {
//...
}
}
}
public ICollection<TValue> GetAll()
{
lock (_syncLock) {
return _internalCache.Values;
}
}
public bool ContainsKey(TKey key)
{
lock (_syncLock)
{
return _internalCache.ContainsKey(key);
}
}
}
The cache above is used by a singleton wrapper:
public class ActivityCache : ICache<string, Activity>
{
private readonly ICache<string, Activity> _cache = new Cache<string, Activity>();
private static readonly ActivityCache _instance = new ActivityCache();
// http://www.yoda.arachsys.com/csharp/singleton.html
static ActivityCache()
{
}
ActivityCache()
{
}
public static ActivityCache Instance
{
get { return _instance; }
}
public Activity this[string activityUrl]
{
get
{
if (string.IsNullOrEmpty(activityUrl))
{
return null;
}
return _cache[activityUrl];
}
set
{
if (string.IsNullOrEmpty(activityUrl))
{
return;
}
_cache[activityUrl] = value;
}
}
public ICollection<Activity> GetAll()
{
return _cache.GetAll();
}
public bool ContainsKey(string key)
{
return _cache.ContainsKey(key);
}
}
This is working fine (I haven't noticed/heard of any errors... yet :) ).
But now I have a problem. I need to reload the cache with new key/values.
Question 1.) Can I implement a "safe" reload method that reloads the cache (the Dictionary in the Cache class) ?
E.g:
public void Reload(IDictionary<TKey, TValue> values)
{
lock (_syncLock)
{
_internalCache.Clear();
foreach (KeyValuePair<TKey, TValue> value in values)
{
/* Problems can (will) occur if another
thread is calling the GetAll method... */
_internalCache[value.Key] = value.Value;
}
}
}
Question 2.) Should I use some IoC container or some other library instead?
Thanks!
Note: I'm using .NET 3.5
use ConcurrentDictionary, then you wont have to deal with Synchronization.
Also, you dont want to reload all the cache items as well. instead you want to do staggering, load the cache objects in the key/value store on demand.
You can use timestamp or some versioning for that. if you reload the data per each key/value pair then you wont have to lock the whole collection.
I really recommend you to use ConcurrentDictionary.
You should lock around GetAll as well.
You could use a double buffer type technique to make the reload less painful :
public void Reload(IDictionary<TKey, TValue> values)
{
cache = new Dictionary<TKey, TValue> ();
foreach (KeyValuePair<TKey, TValue> value in values)
{
cache[value.Key] = value.Value;
}
lock (_syncLock)
{
_internalCache = cache;
}
}
This will work providing you don't mind readers accessing potentially out of date information whilst you call reload.
Related
I am trying to use ConcurrentDictionary to implement a cap limited cache. When the cache reaches its capacity, further additions of new items are rejected. The code snippet is as follows:
var result = this.cache.AddOrUpdate(
key,
(key1) =>
{
if (!this.IsFull())
{
return new List<MyObject> { value };
}
what to return here??
},
(key1, value1) =>
{
value1.Add(value);
return value1;
});
My question here if the cache is full what should I return here? null? or what?
You have two options:
Write a new concurrrent data struct to manage your cache constraints. This is harder but if such a struct is going to be used in several places within your solution thet go for this one.
Delegate cache's constraints management to the class that actually holds the cache. This is easier.
#Kirill Polishchuck answer is an example of the second alternative, but I belive it is not threadsafe so I would change it like so it ends up like:
if (!this.IsFull())
{
// your logic here
this.cache.AddOrUpdate(key, k=> new List<MyObject> { value };);
}
else
{
// logic
}
For the first alternative here is a sample of what you could do to implement it. We implement IDictonary<TKey,TValue> interface and we lock on those operations that require so. Also, the class does not allow further insertions if _maxCount has been surpassed:
public class MaxCountDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly Dictionary<TKey, TValue> _dictionary;
private readonly object _lock;
public MaxCountDictionary(int maxCount) : this(maxCount, EqualityComparer<TKey>.Default) { }
public MaxCountDictionary(int maxCount, IEqualityComparer<TKey> equalityComparer)
{
_lock = new object();
MaxCount = maxCount;
_dictionary = new Dictionary<TKey, TValue>(equalityComparer);
}
public int MaxCount { get; }
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => _dictionary.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public void Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value);
public void Clear()
{
lock (_lock)
{
_dictionary.Clear();
}
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
lock (_lock)
{
return ((IDictionary<TKey, TValue>) _dictionary).Contains(item);
}
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
lock (_lock)
{
((IDictionary<TKey, TValue>) _dictionary).CopyTo(array, arrayIndex);
}
}
public bool Remove(KeyValuePair<TKey, TValue> item) => Remove(item.Key);
public int Count
{
get
{
lock (_lock)
{
return _dictionary.Count;
}
}
}
public bool IsReadOnly => ((IDictionary<TKey, TValue>) _dictionary).IsReadOnly;
public bool ContainsKey(TKey key)
{
lock (_lock)
{
return _dictionary.ContainsKey(key);
}
}
public void Add(TKey key, TValue value)
{
lock (_lock)
{
if (_dictionary.Count < MaxCount) _dictionary.Add(key, value);
}
}
public bool Remove(TKey key)
{
lock (_lock)
{
return _dictionary.Remove(key);
}
}
public bool TryGetValue(TKey key, out TValue value)
{
lock (_lock)
{
return _dictionary.TryGetValue(key, out value);
}
}
public TValue this[TKey key]
{
get
{
lock (_lock)
{
return _dictionary[key];
}
}
set
{
lock (_lock)
{
if (_dictionary.ContainsKey(key) || _dictionary.Count < MaxCount) _dictionary[key] = value;
}
}
}
public ICollection<TKey> Keys
{
get
{
lock (_lock)
{
return _dictionary.Keys.ToArray();
}
}
}
public ICollection<TValue> Values
{
get
{
lock (_lock)
{
return _dictionary.Values.ToArray();
}
}
}
public void AddOrUpdate(TKey key, TValue value, Func<TKey, TValue, TValue> updateValueFactory)
{
lock (_lock)
{
if (_dictionary.ContainsKey(key))
_dictionary[key] = updateValueFactory(key, value);
else if (_dictionary.Count < MaxCount) _dictionary[key] = value;
}
}
}
With this other alternative you simply pass a MaxCount parameter to your collection, you can change it to accept a Func<bool> so that the dictionary can figure out whether to add more items or not, this way you can pass your IsFull method to it.
Beware: This is demo code, it is just a sample, it is not thread safe to enumarate, adjust it to your needs.
I have made an attempt at creating a ThreadSafeSortedDictionary, and I am working with .NET 4.0.
I have had a look at Thread safe SortedDictionary but not confident about the thread safety aspect.
Anyone think this can work, or NOT for a reason I cannot see associated with:
Thread safety - it needs to be thread safe
Performance/Efficiency - I am not majorly concerned about this (unless there is a huge problem with performance)
My code:
public class ThreadSafeSortedDict<TKey, TValue>
{
private readonly SortedDictionary<TKey, TValue> _dict;
private readonly ReaderWriterLockSlim _dictReaderWriterLockSlim;
private readonly ReaderWriterLockSlim _readonlyDictionaryLock;
public Dictionary<TKey, TValue> ReadOnly { get; set; }
public ThreadSafeSortedDict(IComparer<TKey> comparer)
{
_dict = new SortedDictionary<TKey, TValue>(comparer);
_dictReaderWriterLockSlim = new ReaderWriterLockSlim();
_readonlyDictionaryLock = new ReaderWriterLockSlim();
}
public void Add(TKey key, TValue value)
{
_dictReaderWriterLockSlim.EnterWriteLock();
try
{
_dict.Add(key,value);
}
finally
{
_dictReaderWriterLockSlim.ExitWriteLock();
}
SetReadOnlyDictionary();
}
public void AddRange(IEnumerable<KeyValuePair<TKey,TValue>> keyValues)
{
if (keyValues == null) return;
_dictReaderWriterLockSlim.EnterWriteLock();
try
{
foreach (var keyValue in keyValues)
{
Add(keyValue.Key, keyValue.Value);
}
}
finally
{
_dictReaderWriterLockSlim.ExitWriteLock();
}
SetReadOnlyDictionary();
}
public void Remove(TKey key)
{
_dictReaderWriterLockSlim.EnterWriteLock();
try
{
_dict.Remove(key);
}
finally
{
_dictReaderWriterLockSlim.ExitWriteLock();
}
SetReadOnlyDictionary();
}
public void Replace(IEnumerable<KeyValuePair<TKey, TValue>> newKeyValues)
{
if (newKeyValues == null) return;
_dictReaderWriterLockSlim.EnterWriteLock();
try
{
_dict.Clear();
AddRange(newKeyValues);
}
finally
{
_dictReaderWriterLockSlim.ExitWriteLock();
}
}
private void SetReadOnlyDictionary()
{
_readonlyDictionaryLock.EnterWriteLock();
try
{
ReadOnly = GetSortedKeyValues().ToDictionary(x => x.Key, x => x.Value);
}
finally
{
_readonlyDictionaryLock.ExitWriteLock();
}
}
private List<KeyValuePair<TKey, TValue>> GetSortedKeyValues()
{
_dictReaderWriterLockSlim.EnterReadLock();
try
{
return _dict.ToList();
}
finally
{
_dictReaderWriterLockSlim.ExitReadLock();
}
}
}
I don't see any obvious thread-safety issues with your code. To me, the bigger issues are matters of correctness:
A minor problem is that your ReadOnly property has a public setter. This means any code outside the class can set the property at any time, without any synchronization. Your class design should reflect the intended usage. Presumably you don't want any other code to change the property value, so the setter should be private.
A major problem is that while the class name is ThreadSafeSortedDict<TKey, TValue>, there's no publicly accessible view of the data that is sorted. When you set the ReadOnly property, you create a new unsorted dictionary from the original data. Even though you enumerate the source dictionary in order, which is sorted, there are no guarantees that the data in the new dictionary will remain in the order in which it was added. The dictionary class is, by design, an unordered collection.
If you really want to maintain the data in a SortedDictionary<TKey, TValue> object, and present a sorted view of it, you need to use some type of ordered collection as your ReadOnly property type. This could be another SortedDictionary<TKey, TValue>, but since the intent is for the collection to be read-only, IMHO it makes more sense to make the type IReadOnlyDictionary<TKey, TValue>, returning a ReadOnlyDictionary<TKey, TValue> object. And rather than creating a new object every time the sorted dictionary is modified, you can initialize it lazily and invalidate it when the sorted dictionary is modified.
For example:
public class ThreadSafeSortedDict<TKey, TValue>
{
private readonly SortedDictionary<TKey, TValue> _dict;
private IReadOnlyDictionary<TKey, TValue> _readOnly;
private readonly object _lock = new object();
public IReadOnlyDictionary<TKey, TValue> ReadOnly
{
get
{
lock (_lock)
{
if (_readOnly == null)
{
// NOTE: SortedList is faster when populating from already-sorted data
_readOnly = new ReadOnlyDictionary(new SortedList(_dict));
}
}
return _readOnly;
}
}
public ThreadSafeSortedDict(IComparer<TKey> comparer)
{
_dict = new SortedDictionary<TKey, TValue>(comparer);
}
public void Add(TKey key, TValue value)
{
lock (_lock)
{
_dict.Add(key,value);
_readOnly = null;
}
}
public void AddRange(IEnumerable<KeyValuePair<TKey,TValue>> keyValues)
{
if (keyValues == null) return;
lock (_lock)
{
foreach (var keyValue in keyValues)
{
Add(keyValue.Key, keyValue.Value);
}
_readOnly = null;
}
}
public void Remove(TKey key)
{
lock (_lock)
{
_dict.Remove(key);
_readOnly = null;
}
}
public void Replace(IEnumerable<KeyValuePair<TKey, TValue>> newKeyValues)
{
if (newKeyValues == null) return;
lock (_lock)
{
_dict.Clear();
AddRange(newKeyValues);
_readOnly = null;
}
}
}
Using lock instead of the reader-writer lock should not affect performance significantly, if at all, and makes the code a lot more obviously thread-safe. It seems to me that the above should be sufficient. Still, if it's not, some improvements you could make include:
Going ahead and using the reader-writer lock. You'll need to acquire the reader lock in the ReadOnly property, and upgrade it to a writer lock if you need to set the _readOnly field (i.e. if it's set to null). This could improve performance if you have a very large amount of contention on the ReadOnly property.
Not bothering with the custom type, and using ConcurrentDictionary<TKey, TValue> instead, just copying its contents and sorting them after the fact when you need a sorted view of the dictionary. Whether this is useful in your case I can't say, as there's not enough context in the question. If you will still need to implement some type of synchronization to avoid trying to retrieve the sorted view when some other thread is trying to modify the collection, then you'll probably want some kind of wrapper type anyway.
Having your type implement IReadOnlyDictionary<TKey, TValue> rather than having a ReadOnly property. Then you can pass your object as a read-only dictionary object where needed, but code that needs to actually modify the dictionary can still do so via the original type.
Given what information is available in the question at the moment, I'd say option #3 is probably best. It would require the most work, but seems to me to provide the cleanest, most efficient API. You would avoid having to have the ReadOnly property and you would avoid having to make a copy of the collection. The class itself would serve as the read-only copy, and it would automatically be kept up-to-date with respect to the underlying dictionary collection, because the implementation of IReadOnlyDictionary<TKey, TValue> would just defer to the underlying dictionary (with synchronization, of course).
First of all, thanks to #Peter Duniho for the information and answer.
I first attempted using reader writer locks, but had quite a bit of trouble and took the advise to use locks for simplicity.
My solution is modifying Peters answer, because I did not want to lock everytime the ReadOnly dictionary was accessed.
And my ultimate goals for this class are:
At any point in time, I would like to access the ReadOnly collection (and stop users to write to it).
If something in the underlying dictionary gets added/removed, I do not want this to affect other's who are already using/reading/iterating the ReadOnly they have access to.
Here is the solution:
public class ThreadSafeSortedDictionary<TKey, TValue>
{
private readonly SortedDictionary<TKey, TValue> _dict;
private readonly object _sync;
public ReadOnlyDictionary<TKey, TValue> ReadOnly { get; private set; }
public IEnumerable<TValue> Values
{
get { return ReadOnly.Values; }
}
public IEnumerable<TKey> Keys
{
get { return ReadOnly.Keys; }
}
public int Count
{
get { return ReadOnly.Count; }
}
public ThreadSafeSortedDictionary(IComparer<TKey> comparer)
{
_dict = new SortedDictionary<TKey, TValue>(comparer);
_sync = new object();
}
public void Add(TKey key, TValue value)
{
lock (_sync)
{
_dict.Add(key, value);
SetReadOnlyDictionary();
}
}
public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> keyValues)
{
if (keyValues == null) return;
InternalAddRange(keyValues);
}
public void Remove(TKey key)
{
lock (_sync)
{
_dict.Remove(key);
SetReadOnlyDictionary();
}
}
public void Replace(IEnumerable<KeyValuePair<TKey, TValue>> newKeyValues)
{
//Throw exception, because otherwise we'll end up clearing the dictionary
if (newKeyValues == null) throw new ArgumentNullException("newKeyValues");
InternalAddRange(newKeyValues, true);
}
private void InternalAddRange(IEnumerable<KeyValuePair<TKey, TValue>> keyValues, bool clearBeforeAdding = false)
{
lock (_sync)
{
if (clearBeforeAdding) _dict.Clear();
foreach (var kvp in keyValues)
{
_dict.Add(kvp.Key, kvp.Value);
}
SetReadOnlyDictionary();
}
}
private void SetReadOnlyDictionary()
{
lock (_sync)
{
ReadOnly = new DictionaryReadOnly<TKey, TValue>(new SortedList<TKey, TValue>(_dict, _dict.Comparer));
}
}
}
And I used the ReadOnlyDictionary from the answer of Is there a read-only generic dictionary available in .NET?
I used SortedList vs SortedDictionary for the ReadOnly property, because I am creating them quite a few times (during add/remove/replace), and because
1. SortedList perform better in memory
2. are quicker in lookup, and as I am only using them for Read Only purposes, only lookup will be needed.
I have a C# WebAPI that has a query which collates a lot of data. Subsequently, I am using HttpRuntime cache to cache the result object for 10 mins. The problem is, when the cache expires, that person gets a 12 second load. This application utilises 3 delivery servers and we don't have the option of distributed cache.
Using .NET, we can use the cache expired event, but how best to use that without impacting the calling request?
One thought was to have a never expires cache, so that if the main cache is expired, fallback to that, then have a windows service or similar which polls every 5 mins to refresh both caches.
Ideas?
Perhaps caching the results separately to the page cache will help.
Based on http://johnnycoder.com/blog/2008/12/10/c-cache-helper-class/
Since it is static, you could use WCF to refresh at your own pace.
I modified to be static and not http
public static class CacheHelper
{
public static void WriteOutCacheHelper()
{
foreach (KeyValuePair<string, object> cache in Cache)
{
Console.WriteLine(cache.Key);
}
}
public static void WriteOutCacheHelper(string key)
{
Console.WriteLine(Get<object>(key).ToString());
}
public static bool Enabled { get; set; }
private static Dictionary<string, object> _cache;
public static Dictionary<string, object> Cache
{
get
{
if (_cache == null) _cache = new Dictionary<string, object>();
return _cache;
}
}
public static object lockObject = new object();
public static void Add<T>(T o, string key)
{
if (!Enabled) return;
lock (lockObject)
{
if (Exists(key))
Cache[key] = o;
else
Cache.Add(key, o);
}
}
public static void Clear(string key)
{
if (!Enabled) return;
Cache.Remove(key);
}
public static bool Exists(string key)
{
if (!Enabled) return false;
return Cache.ContainsKey(key);
}
public static T Get<T>(string key)
{
if (!Enabled) return default(T);
T value;
try
{
value = (!Exists(key) ? default(T) : (T) Cache[key]);
}
catch
{
value = default(T);
}
return value;
}
public static void ClearAll(bool force = false)
{
if (!force && !Enabled) return;
Cache.Clear();
}
public static List<T> GetStartingWith<T>(string cacheKey) where T : class
{
if (!Enabled) new List<T>();
return Cache.ToList().FindAll(f => f.Key.StartsWith(cacheKey, StringComparison.CurrentCultureIgnoreCase))
.Select(s => s.Value as T).ToList();
}
}
I'm completely new to C#, so I'm about to make a horrible attempt at my own version of an OrderedDictionary unless someone can suggest an alternative.
I need to be able to access my elements by array index, retaining the order they were added, and I also will be frequently updating individual elements using their key.
Is there a collection that allows this on the phone?
If I keep a List and Dictionary will they both be pointing to the same item or is there some kind of pointer thing I have to do?:
Item i = new Item();
list.Add(i);
dict.Add("key", i);
Here's my implementation (comes from the open source OpenNETCF Extensions library):
public class OrderedDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
private Dictionary<TKey, TValue> m_dictionary;
private List<TValue> m_list = new List<TValue>();
private object m_syncRoot = new object();
public OrderedDictionary()
{
m_dictionary = new Dictionary<TKey, TValue>();
}
public OrderedDictionary(IEqualityComparer<TKey> comparer)
{
m_dictionary = new Dictionary<TKey, TValue>(comparer);
}
public void Add(TKey key, TValue value)
{
lock (m_syncRoot)
{
m_dictionary.Add(key, value);
m_list.Add(value);
}
}
public TValue this[int index]
{
get { return m_list[index]; }
}
public TValue this[TKey key]
{
get { return m_dictionary[key]; }
}
public int Count
{
get { return m_dictionary.Count; }
}
public Dictionary<TKey, TValue>.KeyCollection Keys
{
get { return m_dictionary.Keys; }
}
public Dictionary<TKey, TValue>.ValueCollection Values
{
get { return m_dictionary.Values; }
}
public void Clear()
{
lock (m_syncRoot)
{
m_dictionary.Clear();
m_list.Clear();
}
}
public bool ContainsKey(TKey key)
{
return m_dictionary.ContainsKey(key);
}
public bool ContainsValue(TValue value)
{
return m_dictionary.ContainsValue(value);
}
public void Insert(int index, TKey key, TValue value)
{
lock (m_syncRoot)
{
m_list.Insert(index, value);
m_dictionary.Add(key, value);
}
}
public void Remove(TKey key)
{
lock (m_syncRoot)
{
if (ContainsKey(key))
{
var existing = m_dictionary[key];
m_list.Remove(existing);
m_dictionary.Remove(key);
}
}
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return m_dictionary.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Using a List and a Dictionary is probably a good option actually. The "pointer thing" that you're talking about happens by default for Objects in .NET (any class and/or structure). All objects in .NET are passed around by reference.
So, if you use:
Item i = new Item();
list.Add(i);
dict.Add("key",i);
Console.WriteLine(list.Last() == dict["key"]);
Your output will be "true".
Best of luck!
I won't suggest using OrderedDictionary, since it's a non-generic container.
However, if you just want to use it like always. You can port Mono's version of OrderedDictionary.
https://github.com/mono/mono/blob/master/mcs/class/System/System.Collections.Specialized/OrderedDictionary.cs
Here's some tips if you want to port this:
Remove any unavailable interface
Remove serialization-related code
Replace ArrayList with List<object>
Replace Hashtable with Dictionary<object, object>
I require a thread safe collection but are unable to use ConcurrentDictionary as its .NET 4.0, and I need to use .NET 3.5. What are alternatives are out there?
In the end I found what I was after. A nuget package of the TPL backported to 3.5. It can be found here
http://nuget.org/packages/TaskParallelLibrary
Have a look at this article
“Thread safe” Dictionary(TKey,TValue)
For Framework 3.5 I see the following options:
Dictionary + Monitor. Simple wrap to lock
Dictionary + ReaderWriterLock. Better than the previous one, because has got read and write locks. So several threads can read, and just one - write.
Dictionary + ReaderWriterLockSlim. It's just optimisation of the previous one.
Hashtable. From my experience, it's the slowest method. Check Hashtable.Synchronized() method, it's a ready to go solution from Microsoft.
I would use Dictionary + ReaderWriterLock or ReaderWriterLockSlim.
You can create a simple wrapper and only implement what you need. Keep in mind that it is not thread safe to perform an operation on a Dictionary that relies on the result of a previous call. This is exemplified in the TryAdd method.
class ConcurrentMap<K, V>
{
readonly Dictionary<K, V> _map = new Dictionary<K, V>();
public bool TryGetValue(K key, out V value)
{
lock (_map)
{
return _map.TryGetValue(key, out value);
}
}
public bool TryAdd(K key, V value)
{
lock (_map)
{
if (!_map.ContainsKey(key))
{
_map.Add(key, value);
return true;
}
return false;
}
}
public bool TryRemove(K key)
{
lock (_map)
{
return _map.Remove(key);
}
}
}
I just needed that for .Net 3.5... someone's still there back :)
adding my class, added some more functionality than previous attached codes.
public class SafeDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
private readonly object _Padlock = new object();
private readonly Dictionary<TKey, TValue> _Dictionary = new Dictionary<TKey, TValue>();
public TValue this[TKey key]
{
get
{
lock (_Padlock)
{
return _Dictionary[key];
}
}
set
{
lock (_Padlock)
{
_Dictionary[key] = value;
}
}
}
public bool TryGetValue(TKey key, out TValue value)
{
lock (_Padlock)
return _Dictionary.TryGetValue(key, out value);
}
public bool TryAdd(TKey key, TValue value)
{
lock (_Padlock)
{
if (!_Dictionary.ContainsKey(key))
{
_Dictionary.Add(key, value);
return true;
}
return false;
}
}
public bool TryRemove(TKey key)
{
lock (_Padlock)
{
return _dictionary.Remove(key);
}
}
}
internal void Add(TKey key, TValue val)
{
lock (_Padlock)
{
_Dictionary.Add(key, val);
}
}
public bool ContainsKey(TKey id)
{
lock (_Padlock)
return _Dictionary.ContainsKey(id);
}
public List<KeyValuePair<TKey, TValue>> OrderBy(Func<KeyValuePair<TKey, TValue>, TKey> func)
{
lock (_Padlock)
return _Dictionary.OrderBy(func).ToList();
}
public Dictionary<TKey, TValue>.ValueCollection Values
{
get
{
lock (_Padlock)
return _Dictionary.Values;
}
}
public Dictionary<TKey, TValue>.KeyCollection Keys
{
get
{
lock (_Padlock)
return _Dictionary.Keys;
}
}
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
lock (_Padlock)
return _Dictionary.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
lock (_Padlock)
return _Dictionary.GetEnumerator();
}
}