Application Cache and Slow Process

2019-09-17 10:52发布

I want to create an application wide feed on my ASP.net 3.5 web site using the application cache. The data that I am using to populate the cache is slow to obtain, maybe up to 10 seconds (from a remote server's data feed). My question/confusion is, what is the best way to structure the cache management.

private const string CacheKey = "MyCachedString";
private static string lockString = "";

public string GetCachedString()
{
    string data = (string)Cache[CacheKey];
    string newData = "";

    if (data == null)
    {
        // A - Should this method call go here?
        newData = SlowResourceMethod();

        lock (lockString)
        {
            data = (string)Cache[CacheKey];

            if (data != null)
            {
               return data;
            }

            // B - Or here, within the lock?
            newData = SlowResourceMethod();
            Cache[CacheKey] = data = newData;
        }
    }

    return data;
}

The actual method would be presented by and HttpHandler (.ashx).

If I collect the data at point 'A', I keep the lock time short, but might end up calling the external resource many times (from web pages all trying to reference the feed). If I put it at point 'B', the lock time will be long, which I am assuming is a bad thing.

What is the best approach, or is there a better pattern that I could use?

Any advice would be appreciated.

1条回答
贪生不怕死
2楼-- · 2019-09-17 11:55

I add the comments on the code.

private const string CacheKey = "MyCachedString";
private static readonly object syncLock = new object();

public string GetCachedString()
{
    string data = (string)Cache[CacheKey];
    string newData = "";

    // start to check if you have it on cache
    if (data == null)
    {
        // A - Should this method call go here?
        // absolut not here
        // newData = SlowResourceMethod();

        // we are now here and wait for someone else to make it or not
        lock (syncLock)
        {
            // now lets see if some one else make it...
            data = (string)Cache[CacheKey];

            // we have it, send it
            if (data != null)
            {
               return data;
            }

            // not have it, now is the time to look for it.
            // B - Or here, within the lock?
            newData = SlowResourceMethod();
            // set it on cache
            Cache[CacheKey] = data = newData;
        }
    }

    return data;
}

Better for me is to use mutex and lock depended on the name CacheKey and not lock all resource and the non relative one. With mutex one basic simple example will be:

private const string CacheKey = "MyCachedString";
public string GetCachedString()
{
    string data = (string)Cache[CacheKey];
    string newData = "";

    // start to check if you have it on cache
    if (data == null)
    {
        // lock it base on resource key 
        //  (note that not all chars are valid for name)
        var mut = new Mutex(true, CacheKey);

        try
        {   
            // Wait until it is safe to enter.
            // but also add 30 seconds max
            mut.WaitOne(30000);

            // now lets see if some one else make it...
            data = (string)Cache[CacheKey];

            // we have it, send it
            if (data != null)
            {
               return data;
            }

            // not have it, now is the time to look for it.
            // B - Or here, within the lock?
            newData = SlowResourceMethod();
            // set it on cache
            Cache[CacheKey] = data = newData;

        }
        finally
        {
            // Release the Mutex.
            mut.ReleaseMutex();
        }    
    }

    return data;
}

You can also read
Image caching issue by using files in ASP.NET

查看更多
登录 后发表回答