I am after a collection with the following properties:
- threadsafe: it will be used in asp.net and multiple clients could try to add, remove and access members concurrently
- max elements: I want to be able to set an upper bound, a maximum number of elements, at construction time
- TryAdd: a method that works the same as
BlockingCollection<T>.TryAdd(T)
would be perfect, i.e. it would return false if the maximum number of elements has been reached - Dictionary-like: In most other respects a
ConcurrentDictionary
would be perfect, i.e. ability to identify elements by a key, remove any item (not just the first or last, which I think would be the limitation withBlockingCollection
)
Before I attempt to roll my own, my questions are:
- have I missed a built in type that would put a safe ceiling on the number of elements in a collection?
- Is there a way to achieve this functionality with
BlockingCollection
somehow?
Finally, if I do need to try and make my own, what approach should I think about? Is it as simple as a wrapped Dictionary
with locks
?
Example use: A chat room with a defined limit on number of participants could store the connection information of participants and reject new entrants until there is room to enter when full
If you need to create something like a
ConcurrentDictionary
with some extra features(e.g. max elements) I'd go for anAdaptor
that will hold a privateConcurrentDictionary
and expand it where you need to expand it.A lot of method calls will stay with no change(you will simple call your private
ConcurrentDictionary
and do nothing).If you have all these additional requirements isn't it better to create a class that composes a
List
rather than is one? Put the list inside the class you're making.For example, I would say a chat room contains a list rather than being a special type of list. I would have all the max number, get chatter by name etc logic separate from the actual
list
. Then I would use alock
around interactions with the list, or some threadsafe collection likeConcurrentBag
. As far a whether you want a dictionary, it really depends on teh detail of the data and how you're going to be accessing it.The simplest solution is just make a wrapper class that uses a normal dictionary and uses a
ReaderWriterLockSlim
to control thread safe access.This class implements the full
IDictionary<Tkey,TValue>
interface. The way this works is all insertions pass throughTryAdd
, if you are at or above the max size and try to insert a new member you get afalse
fromTryAdd
and aInvalidOperationException
from methods that do not returnbool
.The reason I did not use a
ConcurrentDictionary
is there is no good way to try to check the count before adding a new member in an atomic way, so you would need to lock anyway. You could potentially use a concurrent dictionary and remove all of myEnterReadLock
's and replace theEnterWriteLock
's with normallock
calls, but you would need to do performance testing to see which would do better.If you want methods like
GetOrAdd
it would not be hard to implement yourself.You'll end up with custom implementation anyways, that said there's no built in type that behaves dictionary-like and has capacity limitations...
To make it completely custom, you may go for
ConcurrentHashSet
limiting amount of entries will work for you.Concurrent HashSet<T> in .NET Framework?
Here is a simple implementation for this: