Сжатие словаря слабых ссылок

У меня есть классFoo с собственностьюЯ бы, Моя цель состоит в том, чтобы не было двух случаевFoo с тем жеЯ бы в то же время.

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

static Foo CreateFoo(int id) {
    Foo foo;
    if (!cache.TryGetValue(id, out foo)) {
        foo = new Foo(id);
        foo.Initialize(...);
        cache.Put(id, foo);
    }
    return foo;
}

Кеш реализован в виде словаря <TKey, WeakReference>, основанного на@JaredPar«sСоздание хеш-таблицы WeakReference:

class WeakDictionary<TKey, TValue> where TValue : class {
    private readonly Dictionary<TKey, WeakReference> items;
    public WeakDictionary() {
        this.items = new Dictionary<TKey, WeakReference>();
    }
    public void Put(TKey key, TValue value) {
        this.items[key] = new WeakReference(value);
    }
    public bool TryGetValue(TKey key, out TValue value) {
        WeakReference weakRef;
        if (!this.items.TryGetValue(key, out weakRef)) {
            value = null;
            return false;
        } else {
            value = (TValue)weakRef.Target;
            return (value != null);
        }
    }
}

Проблема в том, что WeakReferences остаются в словаре после сбора мусора. Это подразумевает необходимость некоторой стратегии, как вручную "собирать мусор" мертвых WeakReferences, как объяснено@ Паскаль Куок вЧто происходит с WeakReference после GC WeakReference.Target.

Мой вопрос:Какова лучшая стратегия для сжатия словаря WeakReference?

Варианты, которые я вижу:

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

Пройдите весь словарь по каждомуСтавить а такжеTryGetValueи удалите мертвые WeakReferences. Это несколько противоречит цели словаря, потому что обе операции становятсяНа).

Периодически проходите весь словарь в фоновом потоке. Что было бы хорошим интервалом, учитывая, что я не знаю модель использованияCreateFoo?

Добавьте каждый вставленный KeyValuePair в двусторонний связанный список. Каждый звонокСтавить а такжеTryGetValue осматривает голову списка. Если WeakReference жив, переместите пару в конец списка. Если он мертв, удалите пару из списка и WeakReference из словаря.

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

Есть ли другие стратегии?

Лучшая стратегия - это алгоритм с амортизированной временной сложностью. Существует ли такая стратегия?

Ответы на вопрос(7)

Ваш ответ на вопрос