Question

I have to create thread safe cache of disposable objects. How i see it:

  1. I have some data class, that i want to cache, ex MyData
  2. I'm creating some collection (ConcurrentDictionary for example) for MyData
  3. I have method that creates new instance of MyData, using some key.
  4. When i need to get MyData for some key i check if it exists in my storage - then use it from collection, else creates new instance and put it into collection
  5. I have some event, when i should invalidate cache. On this event i clear storage.

Probles is that MyData is Disposable. I don't know when should i call Dispose method. I can't call Dispose method when clearing collection on clear-cache event, becouse some thread can use this instances of MyData in a moment.

What pattern should i choose?

Was it helpful?

Solution

I can't see much sense with concurrent collection in the case, when consumers of the cache should be able to complete current operation with the item from cache. You really need a synchronization here.

Most obvious you can do here, is to use ReaderWriteLockSlim and a wrapper around regular Dictionary<TKey, TValue>.

When someone wants to use item from cache, it acquires a read access. When someone wants to modify cache (add an item, or invalidate cache at all), it acquires a write access (hence, writer can't invalidate cache, until last reader won't release the lock).

Another option is to consider approach, when you're just catching ObjectDisposedException. But this approach assumes, that currect operation can be interrupted from the outside.

OTHER TIPS

i think you should encapsulate the cache mechanism and no one should call dispose the object that wraps the dictionary should do it without out side intervention ( a Singleton pattern would be good here, and all access to the dictionary should be locked, on the event you invalidate the cache just lock it again dispose of it and clear it. if you need help with the singleton tell me.

If the objects are logically immutable, are somewhat expensive to create, and are known to consume no non-fungible resources and only a modest quantity of fungible ones; and if tracking all references to them would be impractical, you might consider using cache of short weak references. Such a situation would be one of the few times I might consider it reasonable to "rely" upon finalization, since only one object matching a given key would ever exist outside the "freachable" queue (list of objects needing cleanup) at any given time. One advantage of that approach is that provided you avoid resurrecting objects which have become eligible for finalization, your code shouldn't have to worry too much about threading issues in most cases. You'll have to be a periodically clean out entries whose associated weak references have gone dead, and watch out for the possibility that a cache entry might get updated with a new object after it's been recognized as dead, but the GC should ensure that objects don't get cleaned up while anyone's using them.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top