Komprimieren eines WeakReference-Wörterbuchs

Ich habe eine KlasseFoo mit einer ImmobilieIch würde. Mein Ziel ist, dass es keine zwei Fälle von gibtFoo mit dem gleichenIch würde zur selben Zeit.

Also habe ich eine Fabrikmethode erstelltCreateFoo die einen Cache verwendet, um dieselbe Instanz für dieselbe zurückzugebenIch würde.

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

Der Cache ist als Dictionary <TKey, WeakReference> implementiert, basierend auf@JaredPar'sErstellen einer WeakReference-Hashtabelle:

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

Das Problem besteht darin, dass die WeakReferences im Wörterbuch verbleiben, nachdem ihre Ziele über den Müll gesammelt wurden. Dies impliziert die Notwendigkeit einer Strategie zum manuellen "Garbage Collect" toter WeakReferences, wie von erklärt@ Pascal Cuoq imWas passiert mit einer WeakReference nach GC von WeakReference.Target?.

Meine Frage ist:Was ist die beste Strategie, um ein WeakReference-Wörterbuch zu komprimieren?

Die Optionen, die ich sehe, sind:

Entfernen Sie WeakReferences nicht aus dem Dictionary. IMO ist dies schlecht, weil der Cache in der gesamten Lebensdauer meiner Anwendung verwendet wird, undviel von toten WeakReferences werden sich im Laufe der Zeit ansammeln.

Gehen Sie das gesamte Wörterbuch auf jedemStellen undTryGetValueund entferne tote WeakReferences. Dies macht den Zweck eines Wörterbuchs etwas zunichte, da beide Operationen werdenAuf).

Gehen Sie das gesamte Wörterbuch regelmäßig in einem Hintergrund-Thread durch. Was wäre ein gutes Intervall, da ich das Verwendungsmuster von nicht kenneCreateFoo?

Hängen Sie jedes eingefügte KeyValuePair an eine doppelte verknüpfte Liste an. Jeder Anruf anStellen undTryGetValue Untersucht den Kopf der Liste. Wenn die WeakReference aktiv ist, verschieben Sie das Paar an das Ende der Liste. Wenn es tot ist, entfernen Sie das Paar aus der Liste und die WeakReference aus dem Dictionary.

Implementieren Sie eine benutzerdefinierte Hash-Tabelle mit dem geringfügigen Unterschied, dass bei vollem Bucket zunächst tote WeakReferences aus dem Bucket entfernt werden, bevor Sie wie gewohnt fortfahren.

Gibt es noch andere Strategien?

Die beste Strategie ist wahrscheinlich ein Algorithmus mit amortisierter zeitlicher Komplexität. Gibt es eine solche Strategie?

Antworten auf die Frage(7)

Ihre Antwort auf die Frage