C # перезагрузить синглтон кеш - PullRequest
2 голосов
/ 06 декабря 2011

Мне нужно несколько направлений здесь.У меня есть следующий кэш ключа / значения:

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)?

Например:

    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

Ответы [ 2 ]

2 голосов
/ 06 декабря 2011

используйте ConcurrentDictionary , тогда вам не придется иметь дело с синхронизацией.

Кроме того, вы также не хотите перезагружать все элементы кэша. вместо этого вы хотите делать ошеломляющие, загружать объекты кэша в хранилище ключей / значений по требованию.

Вы можете использовать временную метку или некоторые версии для этого. если вы перезагрузите данные для каждой пары ключ / значение, вам не нужно будет блокировать всю коллекцию.

Я действительно рекомендую вам использовать ConcurrentDictionary.

1 голос
/ 06 декабря 2011

Вы должны также заблокировать 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;
    }
}

Это будет работать, если вы не возражаетечитатели получают доступ к потенциально устаревшей информации, пока вы вызываете reload.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...