C# - получить количество ссылок на объект

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

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

  • когда объект больше не требуется ссылка на ресурс, это просто задает значение null. Тогда когда Диспетчеру ресурсов предлагается выгрузить неиспользованные ресурсы, он получает отсчет ссылок (через отражение?) из каждый ресурс. Если счетчик ссылок является одним (менеджер ресурсов будет иметь ссылку на ресурс), выгрузите ресурс.

есть ли способ получить второе решение в C#? Спасибо.

5 ответов


мне кажется, что вы могли бы просто использовать WeakReference от менеджера ресурсов. Остальное сделает ГК. Вам нужно будет сделать небольшой кастинг, но он будет простым и будет работать.

class Manager {
    Dictionary<string, WeakReference> refs =
        new Dictionary<string, WeakReference>();
    public object this[string key] {
        get {
            WeakReference wr;
            if (refs.TryGetValue(key, out wr)) {
                if(wr.IsAlive) return wr.Target;
                refs.Remove(key);
            }
            return null;
        }
        set {
            refs[key] = new WeakReference(value);
        }
    }
}
static void Main() {
    Manager mgr = new Manager();
    var obj = new byte[1024];
    mgr["abc"] = obj;

    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
    Console.WriteLine(mgr["abc"] != null); // true (still ref'd by "obj")

    obj = null;
    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
    Console.WriteLine(mgr["abc"] != null); // false (no remaining refs)
}

пару вещей. Во-первых, объекты не подсчитываются по ссылкам; схемы подсчета ссылок имеют проблему круговой ссылки, в соответствии с которой два объекта ссылаются друг на друга, но в противном случае недоступны и, следовательно, протекают. .NET использует подход пометки и развертки, который не использует счетчики ref.

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

Как вы знаете, что политика GC и ваша политика являются эквивалентными политиками? ГК не был разработан с конкретные производительность необходимо иметь в виду. То есть он был разработан для высвобождения ресурсов, которые действительно являются мусором, а не для достижения какой-либо конкретной цели производительности, которую вы имеете в виду. Делегируя решение GC, вы отказываетесь от возможности настраивать политику кэша в соответствии с вашими потребностями в производительности.


У нас уже есть менеджер ресурсов в .NET, называемый сборщиком мусора. Поэтому очень эффективный подход-установить ссылки на null и ничего не делать.

более прямой ответ: Нет, нет способа получить ссылки to объект.

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


убедитесь, что диспетчер ресурсов использует WeakReferences к своим ресурсам. Таким образом, когда никто не ссылается на ресурсы, они будут иметь право на вывоз мусора.


Как уже говорили другие пользователи, то, что вы пытаетесь достичь, уже сделано GC и может быть настроено с помощью WeakReference.

Это означает, что в управляемых средах, таких как .NET, java и т. д., Это не проблема.

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