HttpRuntime.Cache is not as complete as it could be in terms
of implementation.
Although the internals of HttpRuntime.Cache do protect the
set/get of values within the internal cache structures, it does not help the
consumer of the Cache. There are reasonable, highly publicized patterns for
setting and getting values. Here is a simple example with comments.
Listing 1
string key = "myCustomObjKey";
// attempt to retrieve the data from the cache
CustomObj customObj = HttpRuntime.Cache[ key ] as CustomObj;
// now check the local variable
if ( customObj == null )
{
// the object was null. We need to repopulate it
customObj = GetCustomObj();
// place it in the cache
HttpRuntime.Cache.Insert(
key
, customObj
, null
, DateTime.Now.AddMinutes( 10 )
, Cache.NoSlidingExpiration
);
}
// now it is assumed to be set. We return it to the caller
return customObj;
This is pretty good because we are only checking the Cache
once and working with a local variable (no race condition to deal with). The
data is only repopulated in the cache when there is nothing in the cache
(specifically, when the value returned from the cache cannot be converted to
the specific object).
In a web environment where you may have many threads trying
to retrieve that object, you could have many requests to a page which implement
this logic. If the call to retrieve the new data is very quick, then perhaps
only one request will repopulate this data. But, there is no guarantee that
GetCustomObj() will be called only once while the cache entry is empty. Even if
GetCustomObj() only takes 100 milliseconds to return data, there could be
numerous requests to repopulate this cache. Now suppose our GetCustomObj()
method makes an expensive call, such as to a database. Not only does this
method seem to be less efficient, but many resources could be wasted on your
database. What is a probable solution to the overused resources?