我需要一些指示。 我有以下键/值缓存:
public class Cache<TKey, TValue> : ICache<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> _internalCache;
private readonly object _syncLock = new object();
public Cache()
{
_internalCache = new Dictionary<TKey, TValue>();
}
public TValue this[TKey key]
{
get
{
lock (_syncLock) {
//...
}
}
set
{
lock (_syncLock) {
//...
}
}
}
public ICollection<TValue> GetAll()
{
lock (_syncLock) {
return _internalCache.Values;
}
}
public bool ContainsKey(TKey key)
{
lock (_syncLock)
{
return _internalCache.ContainsKey(key);
}
}
}
上面的缓存由单身包装器使用:
public class ActivityCache : ICache<string, Activity>
{
private readonly ICache<string, Activity> _cache = new Cache<string, Activity>();
private static readonly ActivityCache _instance = new ActivityCache();
// http://www.yoda.arachsys.com/csharp/singleton.html
static ActivityCache()
{
}
ActivityCache()
{
}
public static ActivityCache Instance
{
get { return _instance; }
}
public Activity this[string activityUrl]
{
get
{
if (string.IsNullOrEmpty(activityUrl))
{
return null;
}
return _cache[activityUrl];
}
set
{
if (string.IsNullOrEmpty(activityUrl))
{
return;
}
_cache[activityUrl] = value;
}
}
public ICollection<Activity> GetAll()
{
return _cache.GetAll();
}
public bool ContainsKey(string key)
{
return _cache.ContainsKey(key);
}
}
这工作正常(我没有注意到/听说过任何错误......):)。
但现在我遇到了问题。我需要使用新的键/值重新加载缓存。
问题1。)我可以实现重新加载缓存的“安全”重载方法(Cache类中的Dictionary)吗?
E.g:
public void Reload(IDictionary<TKey, TValue> values)
{
lock (_syncLock)
{
_internalCache.Clear();
foreach (KeyValuePair<TKey, TValue> value in values)
{
/* Problems can (will) occur if another
thread is calling the GetAll method... */
_internalCache[value.Key] = value.Value;
}
}
}
问题2。)我应该使用一些IoC容器还是其他库?
谢谢!
注意:我正在使用.NET 3.5
答案 0 :(得分:2)
使用ConcurrentDictionary,那么你就不必处理同步了。
此外,您也不想重新加载所有缓存项目。相反,你想要做错,按需加载键/值存储中的缓存对象。
您可以使用时间戳或某些版本控制。如果你为每个键/值对重新加载数据,那么你就不必锁定整个集合。
我真的建议你使用ConcurrentDictionary。
答案 1 :(得分:1)
你也应该锁定GetAll。
你可以使用双缓冲类型技术来减轻重载:
public void Reload(IDictionary<TKey, TValue> values)
{
cache = new Dictionary<TKey, TValue> ();
foreach (KeyValuePair<TKey, TValue> value in values)
{
cache[value.Key] = value.Value;
}
lock (_syncLock)
{
_internalCache = cache;
}
}
如果您在调用重新加载时不介意读者可能会访问可能过时的信息,这将有效。