C # Re-Root Ссылка на объект, использующий события до утилизации GC, шаблон самозависимости Ergo и эффективный сбор памяти / ЦП - PullRequest
0 голосов
/ 08 сентября 2010

Я думал, что это будет интересная картина. Коллекция объектов хранится в классе менеджера. Когда объект не нужен, он удаляется из коллекции. Если он снова нужен, и GC еще не утилизировал его, опросите экземпляр существующего объекта со слабым событием. Например:

class Manager
{
    //--- Events ---

    public event SearchingForInstanceEventHandler SearchingForInstance;


    //--- Fields ---

    List<OneOfMany> _many = new List<OneOfMany>();


    //--- Constructors ---

    public Manager()
    {
        // Create several OneOfMany instances.
        _many.Add(new OneOfMany(this, "C:\file1.txt"));
        _many.Add(new OneOfMany(this, "C:\file2.txt"));
        _many.Add(new OneOfMany(this, "C:\file3.txt"));

        // Erase the strong references to one or more OneOfMany instances.
        _many.Clear();

        // Attempt to find and reuse a previously generated instance, if the GC hasn't reclaimed it.
        SearchingForInstanceEventArgs e = new SearchingForInstanceEventArgs("C:\file2.txt");
        OnSearchingForInstance(e);

        OneOfMany oneOfMany = e.OneOfMany;

        // If a previously generated instance does not exist or has already been reclaimed by the GC, create a new one.
        if (oneOfMany == null)
            oneOfMany = new OneOfMany(this, "C:\file2.txt");

        // Store a reference to it while it is needed.
        _many.Add(e.OneOfMany);
    }


    //--- Protected Methods ---

    protected virtual void OnSearchingForInstance(SearchingForInstanceEventArgs e)
    {
        if (SearchingForInstance != null)
            SearchingForInstance(this, e);
    }
}

class OneOfMany
{
    //--- Fields ---

    string _key;

    Manager _manager;


    //--- Constructors ---

    public OneOfMany(Manager manager, string key)
    {
        _manager = manager;
        _key = key;

        _manager.SearchingForInstance += new SearchingForInstanceEventHandler(_manager_SearchingForInstance);

        // INSERT HERE: Long process generating much data (worth reusing if still exists in memory, and worth freeing if not needed)
    }


    //--- _manager Event Handlers ---

    void _manager_SearchingForInstance(object sender, SearchingForInstanceEventArgs e)
    {
        // If this is the instance the manager is searching for, return a reference to this.
        if (e.Key == _key)
            e.OneOfMany = this;
    }
}

class SearchingForInstanceEventArgs : EventArgs
{
    //--- Public Constructors ---

    public SearchingForInstanceEventArgs(string key)
    {
        Key = key;
    }


    //--- Public Properties ---

    public string Key { get; private set; }

    public OneOfMany OneOfMany{ get; set; }
}

delegate void SearchingForInstanceEventHandler(object sender, SearchingForInstanceEventArgs e);

Это может быть использовано для использования памяти, которую GC еще не освободил, и он может использовать GC для автоматического управления зависимостями для вас. Например, если класс OneOfMany ссылается на другие экземпляры OneOfMany (и зависит от них), вы можете добавить новые ссылки (т.е. зависимости), запросив существующий экземпляр, который вам нужен (с событием), и GC автоматически удалит экземпляры больше не зависели от. Это отличается от хранения всех экземпляров OneOfMany в коллекции и запроса коллекции на существующий экземпляр необходимой зависимости, а также необходимости обходить дерево зависимостей, чтобы вручную удалить некорневые зависимости.

Однако меня беспокоит, что если экземпляр повторно укоренен в GC во время работы GC? Можно ли сделать ссылку OneOfMany с корнями в GC между моментом, когда GC осуждает OneOfMany, и временем, когда он его уничтожает? Если нет, можно ли синхронизировать GC с этим шаблоном?

РЕДАКТИРОВАТЬ: Если текущий метод подписки на событие не является слабым, то замените его на слабый.

1 Ответ

0 голосов
/ 08 сентября 2010

Я не уверен, почему ответ, который я собирался отметить Accepted, был удален, но ответ выглядит примерно так:

Поскольку сильные ссылки можно произвольно извлечь из слабых ссылок, код в OPдолжен работать, предполагая, что не используется проверенная библиотека кеширования.

К ранее опубликованному плакату с ответом о принятом ответе: Извините, под re-root я имел в виду повторную привязку.И, спасибо, я не знал о воскресении объекта.

...