I’d like to share this piece of code with you all.
Usually, when you use the System.Web.Cache classes, you do something like:
object x = Cache[blabla];
if(x == null) //not in cache
{
x = …..;
// add to cache
Cache.Add(x, …);
}
// do something with x here.
Now this is not very thread-safe, because when 2 threads arrive at the ‘if’ at the same time, the object is constructed twice. The second one to complete will just overwrite the cached result of the first one (get it?).
So, in order to avoid this you can add a ‘lock’ statement around this to avoid filling the cache twice.
lock(typeof(ClassName))
{
…
}
This will essentially avoid that 2 threads will enter the same code at the same time.
The problem with this approach is that there is a significant amount of code for every time that you want to read or write to the cache. The code is very error-prone but it is basically the same pattern over and over.
With generics and delegates you can develop a function that behaves like so:
object x = Cached.Get<object>(“cacheKey”, TimeSpan.FromSeconds(5),
() => new object()
);
The lambda expression ()=> new object is the fragment of code that is executed to populate the cache. The “cacheKey” is some sort of string that uniquely defines what information you want to retrieve. The key should in theory contain all the parameters for your population method.
Now there is a huge potential problem inside the Get() method. The lock statement (typeof(ClassName)) inside is essentially the same one over and over, so *all* calls through this method will be blocked and serialized, thus reducing concurrency to zero. If you have long-running or expensive population methods (you will, because that is why you are caching) you’ll be slowing the system to a halt.In effect, you’d want a separate lock for every 'cache key’ literal.
To overcome this problem, I developed an implementation that generates a new lock for every key. However, when reading and updating the HttpUtility Cache you should be very careful for race conditions.
CacheUtility.cs (7,11 kb)
This class provides strongly-typed access to the HttpCache. It also provides helper methods to flush a single or all elements that were cached using this method, and also a way to determine groups of cached elements. This way you can flush only a subsection of your cache.
Currently rated 4.0 by 1 people
- Currently 4/5 Stars.
- 1
- 2
- 3
- 4
- 5