WeakReference держать объект только в 1 поколении? - PullRequest
0 голосов
/ 19 марта 2019

Я экспериментировал с использованием класса WeakReference, но не ожидал, что он не удержит объект от следующей сборки мусора. Почему?

У меня нет знаний о практическом использовании этого класса.

Код вызывает другую сборку мусора после того, как я установил для myObject значение null.

Редактировать: В конце else, если строка myObject не расположена, это потому, что компилятор знает, что объект WeakReference wr все еще используется в коде, так что сборщик мусора не возвращает его?

 class Program
{
    static void Main(string[] args)
    {
        MyObject myObject = new MyObject(25);
        WeakReference wr = new WeakReference(myObject);

        if (wr.IsAlive) Console.WriteLine("Alive");

        myObject = null;

        GC.Collect();
        if (wr.IsAlive) Console.WriteLine("Still alive");
        else if(!wr.IsAlive) Console.WriteLine("Dead");

        //
        //edit: added this 
        GC.Collect();
        if (wr.IsAlive) Console.WriteLine("Still alive");
        else if (!wr.IsAlive) Console.WriteLine("Dead");
        //edit end
        Console.ReadKey();
    }
}

class MyObject : IDisposable
{
    private bool disposed = false;
    private int id = 0;
    public MyObject(int id)
    {
        this.id = id;
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected void Dispose(bool disposing)
    {
        Console.WriteLine("disposed {0}", id);
        if (!disposed)
        {
            if (disposing)
            {
                //free managed
            }
            //free unmanaged
            disposed = true;
        }
    }

    ~MyObject()
    {
        Dispose(false);
    }
}

Ответы [ 2 ]

0 голосов
/ 19 марта 2019

Короткий ответ, почему ваш объект не переживает первую коллекцию: есть 2 типа слабых ссылок: короткая и длинная.Короткие данные собираются сразу, в то время как длинные собираются только после завершения их финализаторов - то есть длинная слабая ссылка должна иметь финализатор, который верен для вашего случая, но другое обязательное требование состоит в том, что он должен быть создан с параметром trackResurrection, установленным в true(по умолчанию false).Финализаторы все равно выполняются во время второй коллекции, но с trackResurrection, установленным на false, объект не отслеживается, а его ссылка установлена ​​на ноль (однако формально он жив до финализации, но не может быть доступен).

0 голосов
/ 19 марта 2019

В конце else, если строка myObject не расположена, это потому, что компилятор знает, что объект WeakReference wr все еще используется в коде, так что сборщик мусора не возвращает его?

Нет, это потому, что вы запускаете приложение с подключенным отладчиком. Пожалуйста, прочитайте @Hans Passant ответ здесь для деталей.

Если вы создаете приложение в режиме выпуска и запускаете его без подключенного отладчика, вы должны увидеть, как «Alive», «Dead» и «Dead» выводятся на консоль. Я делаю.

Вам также следует удалить финализатор из класса MyObject, поскольку вы не используете неуправляемые ресурсы.

...