Как лучше реализовать кеш управления WPF?

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

Вот одна простая форма кэша управления:

public static class ControlCache<T> where T : Visual, new()
{
    private static Dictionary<T, bool> m_Cache = new Dictionary<T, bool>();

    public static T GetInstance()
    {
        if (m_Cache.Count == 0)
            return new T();
        else
        {
            var inst = m_Cache.First();
            m_Cache.Remove(inst.Key);
            return inst.Key;
        }
    }

    static int MAX_COUNT = 300;

    public static void Release(T ctrl)
    {
        if (ctrl != null && m_Cache.Count < MAX_COUNT && !m_Cache.ContainsKey(ctrl))
            m_Cache[ctrl] = true;
    }
}

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

Я ищу стратегию. Как определить, что элемент управления (или объект) недоступен, и вернуть его в мой кеш, а не возлагать на потребителя ответственность за это?

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

Что такое хороший способ?


person ILIA BROUDNO    schedule 02.07.2015    source источник
comment
Если вы хотите знать, был ли объект завершен/собран мусор, вы можете сохранить слабую ссылку на него и проверить свойство IsAlive, чтобы определить, была ли ссылка удалена сборщиком мусора. См. msdn.microsoft.com/en- мы/библиотека/   -  person Ron Beyer    schedule 02.07.2015
comment
Рон, я просмотрел WeakReferences, прежде чем написать вопрос. Я не упомянул их, потому что они не дают решения того, о чем я спрашиваю. Они сообщают вам, БЫЛ ли объект БЫЛ сборщиком мусора. Существует также способ получить уведомление, когда он будет собран: stackoverflow.com/questions/1145529/ также это сделает финализатор объекта. Чего не хватает, так это способа безопасно вернуть его и способа узнать, что он недоступен сразу (а не тогда, когда сборщик мусора приступит к его очистке).   -  person ILIA BROUDNO    schedule 02.07.2015
comment
Я почти уверен, что как только все ссылки на объект будут освобождены и этот объект будет готов к сборке мусора, вы не сможете перехватить и вернуть объект. Как только запускается финализатор объектов или метод Dispose, этот объект должен считаться непригодным для использования. Поскольку вы не можете контролировать, когда ваш пользователь кеша вызывает финализатор или Dispose, вы должны считать, что он исчез, как только вы передаете объект.   -  person Ron Beyer    schedule 02.07.2015
comment
Да, именно поэтому в своем посте я сказал, что эта практика обычно считается плохой по нескольким веским причинам... :)   -  person ILIA BROUDNO    schedule 02.07.2015