Подтвердить что ты не робот

Почему мой деструктор никогда не запускается?

У меня есть пустая Winform с деструкторным методом

public partial class Form1 : Form
{
    public Form1()
    {
        System.Diagnostics.Trace.WriteLine("Form1.Initialize " + this.GetHashCode().ToString());
        InitializeComponent();
    }
    ~Form1()
    {
        System.Diagnostics.Trace.WriteLine("Form1.Dispose " + this.GetHashCode().ToString());
    }
}

Когда форма уничтожена, я хочу, чтобы она записывалась в окно вывода:

(Form1 opened)
Form1.Initialize 41149443
(Form1 closed)
Form1.Dispose 41149443

MSDN предлагает три способа реализации деструктора:

Однако ни один из этих способов не записывает "Form1.Dispose 41149443" в окно вывода. Поэтому я не могу сказать, была ли форма уничтожена или нет. Предложения?

Должен ли я отказаться от надежды на достижение этого из-за неопределенности сборщика мусора?

Есть ли другой способ узнать, был ли собран мусор из Form1?

4b9b3361

Ответ 1

Только один из трех способов реализации деструктора, который вы перечисляете, фактически включает деструктор и ~Destructor().

Если вы реализуете IDisposable и удаляете свой объект, тогда будет выполняться код в Dispose, но нет причин думать, что ваш деструктор будет.

Я думаю, что вы преследуете невозможное здесь. Деструкторы работают так же, как и когда сборщик мусора так декретирует. Это не то, что у вас есть контроль. GC полностью отвечает своим правам, чтобы сформировать мнение о том, что запуск деструкторов просто тратит время, и, если есть много памяти, это сформирует это мнение.

Если вам нужно предсказуемое удаление, финализация и т.д., используйте IDisposable.

Ответ 2

Если вы не изучаете сбор мусора, деструктор не является местом для вашей трассировки. Вы должны посмотреть на Dispose (который можно переопределить в форме). Это происходит после освобождения неуправляемого ресурса (например, вашего дескриптора окна).

protected override void Dispose(bool disposing)
{
   System.Diagnostics.Trace.WriteLine(
      "Form1.Dispose " + (disposing ? "disposing " : "")
      + this.GetHashCode().ToString());
   base.Dispose (disposing);
}

Если вы хотите увидеть, была ли удалена форма/элемент управления, используйте свойство Control.IsDisposed.

Изменить: из-за GC.SuppressFinalize ваш метод Finalize (синтаксис деструктора в С#) никогда не будет выполняться, если Dispose вызывается явно (или с помощью фреймворка).

Для получения дополнительной информации см. Реализация метода удаления.

Ответ 3

Да, вы, вероятно, должны отказаться от идеи деструктора, потому что они не детерминированы по своей природе. Я не уверен, почему вам нужно иметь форму, а не просто закрытую, но просто закрыть ее должно быть достаточно в большинстве случаев.

Вы можете использовать IDisposable, но это зависит от того, зачем вам нужна форма для сбора мусора. Если вам нужно повторно использовать его, просто создайте другой экземпляр.

Ответ 4

Форма получает мусор, собранный, когда не существует ссылок и появляется сборщик мусора. Вы можете заставить сборщик мусора вызывать GC.Collect(). Вы не должны ссылаться на какой-либо другой объект в Finalizer (aka destructor), потому что объект, возможно, уже был собран мусором.

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

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

EDIT: Если ваша проблема заключается в том, что вы не видите вывод трассировки, вам может потребоваться включить автозапуск на

<configuration>
  <system.diagnostics>
    <trace autoflush="true" />
  </system.diagnostics>
</configuration>

ИЗМЕНИТЬ 2: Может быть внешняя ссылка на вашу форму, такую ​​как зарегистрированный обработчик событий. Я бы предложил добавить кнопку в области администрирования вашего приложения, которая выполняет следующий код:

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

Подобным образом сборщик мусора должен работать и должен уничтожить вашу форму (установить контрольную точку в финализатор). Если нет, у вас есть ссылка на объект, который должен быть уничтожен.

Ответ 5

Добавить событие FormClosed в конструктор.

т

this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(Form1_FormClosed);

Затем создайте соответствующую функцию для обработки события.

Ответ 6

Вы можете попробовать обернуть свою форму в объекте WeakReference, а затем проверить его свойство IsAlive, чтобы определить, был ли собран мусор. Но, да... в соответствии с другими ответами вам может быть лучше оставить его и доверять GC, чтобы выполнить свою работу!