Kompaktowanie słownika WeakReference

Mam klasębla z nieruchomościąID. Moim celem jest to, że nie ma dwóch przypadkówbla z tym samymID w tym samym czasie.

Więc stworzyłem metodę fabrycznąUtwórzFoo który używa pamięci podręcznej w celu zwrócenia tej samej instancji dla tego samegoID.

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;
}

Pamięć podręczna jest zaimplementowana jako słownik <TKey, WeakReference> na podstawie@JaredParjestBudowanie Hashtable 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);
        }
    }
}

Problem polega na tym, że WeakReferences pozostają w słowniku po tym, jak ich cele zostały zebrane. Oznacza to potrzebę jakiejś strategii, jak ręcznie „zbierać śmieci” martwych WeakReferences, jak wyjaśniono w@Pascal Cuoq wCo dzieje się z WeakReference po GC WeakReference.Target.

Moje pytanie brzmi:Jaka jest najlepsza strategia na kompaktowanie słownika WeakReference?

Widzę następujące opcje:

Nie usuwaj WeakReferences ze słownika. IMO to źle, ponieważ pamięć podręczna jest używana przez cały okres mojej aplikacji idużo martwych WeakReferences z czasem się zgromadzi.

Przejdź cały słownik na każdymPołożyć iTryGetValuei usuń martwe WeakReferences. To pokonuje nieco cel słownika, ponieważ obie operacje stają sięNa).

Regularnie chodź po całym słowniku w wątku w tle. Jaki byłby dobry interwał, biorąc pod uwagę, że nie znam wzoru użyciaUtwórzFoo?

Dołącz każdą wstawioną parę KeyValuePair do podwójnie zakończonej listy połączonej. Każde połączenie doPołożyć iTryGetValue analizuje głowę listy. Jeśli WeakReference jest żywa, przenieś parę na koniec listy. Jeśli jest martwy, usuń parę z listy i WeakReference ze słownika.

Zaimplementuj niestandardową tablicę mieszającą z niewielką różnicą, że gdy wiadro jest pełne, martwe WeakReferences są najpierw usuwane z wiadra przed kontynuowaniem jak zwykle.

Czy są inne strategie?

Najlepszą strategią jest prawdopodobnie algorytm o zamortyzowanej złożoności czasowej. Czy taka strategia istnieje?

questionAnswers(7)

yourAnswerToTheQuestion