C# 对路径的访问被拒绝互斥
以下是我的方法:C# 对路径的访问被拒绝互斥,c#,asp.net,.net,asp.net-mvc,multithreading,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); M
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
,该路径是我的缓存密钥,但被拒绝。你觉得我的代码有问题吗?我该如何解决这个问题?这些方法在我的控制器的操作中被调用,特定的多个用户可以使用相同的用户名登录。您需要锁定HttpRuntime.Cache对象,而不是密钥
HttpRuntime.Cache不是线程安全的
我更喜欢使用带锁的MemoryCache,因为MemoryCache不是线程安全的:
锁定键不能在静态方法中此代码可以让您更轻松:
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
}
你这是什么意思?我已经使用WaitOne而不仅仅是键锁定了整个代码。锁定必须在对象级别,或者在静态中使用用于静态方法的静态全局对象,您使用的是内部局部变量而不是静态外部方法变量。这是不正确的。互斥体需要一个对象,我通过字符串的方式进行锁定,所以锁是按照每个用户建立的。像MyObjSuperman1,MyObjSuperman2等等。
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());