Mutex拒绝访问路径

时间:2018-04-24 09:16:38

标签: c# asp.net .net asp.net-mvc multithreading

这些是我的方法:

public static string CacheKey(string userName)
        {
            return "MyObj" + userName;
        }

private static MyObj CachedObj(string userName)
        {
            string cacheKey = CacheKey(userName);            

            MyObj cachedBW = HttpRuntime.Cache[cacheKey] as MyObj;
            if (cachedBW == null)
            {
                Mutex bwMutex = new Mutex(false, cacheKey);
                if (bwMutex.WaitOne(Constant.LOCKING_TIMEOUT))
                {
                    try
                    {
                        cachedBW = HttpRuntime.Cache[cacheKey] as MyObj;
                        if (cachedBW == null)
                        {
                            cachedBW = InitialisedBusinessWrapper();
                            HttpRuntime.Cache.Add(cacheKey, cachedBW, null,
                                System.Web.Caching.Cache.NoAbsoluteExpiration,
                                TimeSpan.FromMinutes(INACTIVITY_TIMEOUT), CacheItemPriority.Normal, null);
                            return cachedBW;
                        }
                        else
                            return cachedBW;
                    }
                    finally
                    {
                        bwMutex.ReleaseMutex();
                    }
                }
                else
                    throw new Exception("Timed out waiting");
            }
            else
                return cachedBW;

        }

我一次又一次地访问路径MyObjUsername,这是我的缓存密钥被拒绝。你看到我的代码有什么问题吗?我该如何解决?在我的控制器操作中调用这些方法,并且可以使用相同的用户名登录特定的多个用户。

3 个答案:

答案 0 :(得分:0)

您需要锁定HttpRuntime.Cache对象而不是密钥

HttpRuntime.Cache不是线程安全的

我更喜欢使用带锁定键的MemoryCache,因为MemoryCache不是线程安全的:

https://docs.microsoft.com/en-us/dotnet/api/system.runtime.caching.memorycache?view=netframework-4.7.1

答案 1 :(得分:0)

// this is to lock multiple calls to the static method and lock the Cache 
// must not be inside the static method
private static readonly object _lock = new object();

private static MyObj CachedObj(string userName)
{
     lock(_lock){
            //here safe to add, update or delete from the Cache 
            // since _lock is a global lock to all static method calls
     }
}

锁定键不能在静态方法

答案 2 :(得分:0)

此代码可以让您更轻松:

public static class WebCache
{
    #region Private Fields

    private static readonly MemoryCache _cache = MemoryCache.Default;

    private static readonly HashSet<string> _keysList = new HashSet<string>();

    private static readonly object _lock = new object();

    #endregion Private Fields

    #region Public Methods

    public static T GetUpdate<T>(string key, Func<T> getValue)
    {
        if (_cache[key] == null) { Update(key, getValue); }

        return (T)_cache[key];
    }

    public static void Remove(string key)
    {
        lock (_lock)
        {
            _cache.Remove(key);
            _keysList.Remove(key);
        }
    }

    public static void RemoveAll()
    {
        string[] keyArray = new string[_keysList.Count];
        _keysList.CopyTo(keyArray);
        foreach (string key in keyArray) { lock (_lock) { _cache.Remove(key); } }
        lock (_lock) { _keysList.Clear(); }
        keyArray.ExClear();
    }

    public static void Update<T>(string key, Func<T> getValue)
    {
        CacheItemPolicy policy = new CacheItemPolicy
        {
            AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration,
            SlidingExpiration = new TimeSpan(2, 0, 0),
            RemovedCallback =
                (arg) => { lock (_lock) { _keysList.Remove(arg.CacheItem.Key); } },
            Priority = CacheItemPriority.Default
        };

        Remove(key);

        lock (_lock) { _cache.Add(key, getValue(), policy); _keysList.Add(key); }
    }

    #endregion Public Methods
}

用法:

object myCachedObj = WebCache.GetUpdate("KeyName", () => GetRequiredObject());