HttpRuntime Close не удаляет элементы из кэша, как рекламируется - PullRequest
1 голос
/ 17 апреля 2009

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

Я нашел много статей, в которых говорилось, что правильный способ очистки кэша - вызвать HttpRuntime.Close ()

Однако в моей настройке модульных тестов я вызываю инкапсулированную функцию HttpRuntime.Close (), и кэш НЕ очищается.

Я ожидал, что он выполнит что-то похожее на

foreach (DictionaryEntry cacheItem in HttpRuntime.Cache)
{
    HttpRuntime.Cache.Remove(cacheItem.Key.ToString());
}

Цикл foreach прекрасно работает в моей инкапсулированной функции, но Close () никогда не работает правильно.

Я неправильно понимаю цель HttpRuntime.Close () или здесь происходит что-то более зловещее?

Ответы [ 3 ]

9 голосов
/ 17 апреля 2009

Не используйте Close, он делает больше, чем говорят документы. И в документах также сказано не использовать его при обработке обычных запросов ...

Это отраженный источник Close ():

[SecurityPermission(SecurityAction.Demand, Unrestricted=true)]
public static void Close() {
    if (_theRuntime.InitiateShutdownOnce()) {
        SetShutdownReason(ApplicationShutdownReason.HttpRuntimeClose, "HttpRuntime.Close is called");
        if (HostingEnvironment.IsHosted) {
            HostingEnvironment.InitiateShutdown();
        } else {
            _theRuntime.Dispose();
        }
    }
}

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

Итак, попробуйте это вместо этого, что не изменит то, над чем оно зацикливается:

List<string> toRemove = new List<string>();
foreach (DictionaryEntry cacheItem in HttpRuntime.Cache) {
    toRemove.Add(cacheItem.Key.ToString());
}
foreach (string key in toRemove) {
    HttpRuntime.Cache.Remove(key);
}

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

4 голосов
/ 15 января 2011

Я понимаю проблему с перечислением, но по какой-то причине в кэше не возникает проблем с удалением элемента при просмотре списка.

Если вы перейдете к подробной реализации, вы обнаружите, что Enumerator создан CacheSingle.CreateEnumerator, для экземпляра создается новый экземпляр Hashtable.

Вот почему вы можете выполнять удаление в цикле foreach.

0 голосов
/ 06 января 2013

Вы можете просто реализовать свой собственный класс Cache, отметьте следующий:

 public sealed class YourCache<T>
{
    private Dictionary<string, T> _dictionary = new Dictionary<string, T>();

    private YourCache()
    {
    }

    public static YourCache<T> Current
    {
        get
        {
            string key = "YourCache|" + typeof(T).FullName;
            YourCache<T> current = HttpContext.Current.Cache[key] as YourCache<T>;
            if (current == null)
            {
                current = new YourCache<T>();
                HttpContext.Current.Cache[key] = current;
            }
            return current;
        }
    }

    public T Get(string key, T defaultValue)
    {
        if (string.IsNullOrWhiteSpace(key))
            throw new ArgumentNullException("key should not be NULL");

        T value;
        if (_dictionary.TryGetValue(key, out value))
            return value;

        return defaultValue;
    }

    public void Set(string key, T value)
    {
        if (key == null)
            throw new ArgumentNullException("key");

        _dictionary[key] = value;
    }

    public void Clear()
    {
        _dictionary.Clear();
    }
}

Вы можете вызывать элементы из кэша или даже очищать их, используя следующее:

 // put something in this intermediate cache
YourCache<ClassObject>.Current.Set("myKey", myObj);

// clear this cache
YourCache<ClassObject>.Current.Clear();
...