Утилизировать форму после закрытия

У меня возникла новая проблема с открытием и закрытием формы на С#.

Моя проблема заключается в том, как удалить форму после закрытия.

вот мой код:

Program.cs:

static class Program
{
    public static Timer timer;

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        timer = new Timer { Interval = 1000};
        timer.Start();

        Application.Run(new Form1());
    }
}

Form1.cs:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Form2 form = new Form2();
        form.ShowDialog();
       /// I've tried Dispose() method . but didn't work
    }
}

Form2.cs:

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    private void Form2_Load(object sender, EventArgs e)
    {
        Program.timer.Tick += timer_Tick;    
        Close();
        // I've tried Dispose() method instead of Close() but didn't work
    }

    private int count = 0; 
    void timer_Tick(object sender, EventArgs e)
    {
        count++;
        if (count == 5) MessageBox.Show("");
    }
}

Отредактировано: Мой вопрос: почему окно сообщения показывает через 5 секунд, когда форма 2 закрылась!

Ответ 1

Изменить: этот вопрос оказывается о Dispose.

Во-первых, Dispose имеет отношение к сбору мусора. Выполняется следующее:

  • У вас есть глобальный экземпляр Timer
  • Вы создаете form2
  • Form2 подписывается на таймер
  • Форма 2 закрыта и/или расположена
  • Событие Timer срабатывает, увеличивает счетчик и показывает MessageBox
  • Событие таймера продолжает стрелять до закрытия приложения.

Главное, чтобы понять, что Close/Dispose изменяет только статус формы, они не могут (не могут) "удалить" экземпляр. Таким образом, существует (закрытая) форма, поле счетчика все еще существует, и событие срабатывает.


ОК, часть 1:

Блок

A using () {} будет лучше, но это должно работать:

    private void button1_Click(object sender, EventArgs e)
    {
        Form2 form = new Form2();
        form.ShowDialog();
       /// I've tried Dispose() method . but didn't work
        form.Dispose(); // should work
    }

Если нет, опишите, что "не работает".


    private void Form2_Load(object sender, EventArgs e)
    {
        Program.timer.Tick += timer_Tick;    
        Close();
       /// I've tried Dispose() method instead of Close() . but didn't work
    }

Это странно, но я буду считать, что это искусственный код для вопроса.

Теперь ваш глобальный Program.Timer хранит ссылку на ваш экземпляр Form2 и не будет собирать его. Это не мешает ему быть Disposed/Close, поэтому ваш таймер будет продолжать стрельбу по закрытой форме, и это обычно будет терпеть неудачу и вызовет другие проблемы.

  • Не делайте этого (дайте Form2 собственный таймер)
  • Используйте событие FormClosed для отмены подписки: Program.timer.Tick -= timer_Tick;

Ответ 2

Самый простой и надежный способ утилизации Form после использования - это использовать использование внутри используемого блока

using (Form2 form = new Form2()) {
  form.ShowDialog();
}

Блок использования в С# представляет собой конструкцию, которая существенно расширяет приведенное выше в следующий код.

Form2 form;
try {
  form = new Form2(); 
  ...
} finally {
  if ( form != null ) {
    form.Dispose();
  }
}

Ответ 3

Это старый вопрос, но он затрагивает некоторые интересные моменты о том, как работают объекты. Форма, по существу, является объектом. Все объекты одного и того же класса используют одни и те же методы, но каждый имеет свои собственные данные. Что это значит? Это означает, что закрытие или удаление объекта не освобождает/не удаляет/не удаляет из памяти какой-либо код. Только данные. Все, что касается объектов вообще, независимо от языка.

Теперь, в частности, о вашем коде. Посмотрим, что делает линия Program.timer.Tick += timer_Tick;. Это дает указатель на вашу функцию в объекте Form на объект таймера. Итак, теперь, независимо от того, что вы делаете с объектом Form, объект timer будет продолжать вызывать эту функцию. Объект таймера не заботится о вашей Форме и даже не знает о существовании объекта Form. Он заботится только о функции, которой вы передавали указатель. Что касается объекта таймера, эта функция является автономной функцией.

Что делает Form.Close()? Form.Close() удаляет ресурсы, используемые формой, ака, маркирует элементы управления формой для сбора мусора, если форма не отображается с помощью ShowDialog. В этом случае Dispose() необходимо вызвать вручную. MSDN

Излишне говорить (или, может быть, не так уж и нужно), что если закрытие/удаление формы очистит функцию из памяти, объект таймера будет иметь недопустимый указатель, и ваша программа сработает через 5 секунд.

Ответ 4

Возможно, я читаю вопрос неправильно, но я думаю, что джентльмены должны знать, что для закрытия формы (например, form2), открытой как Form2.ShowDialog(), вам нужно установить Form2.DialogResult в Form2. Просто установка этого члена - это все, что требуется, чтобы закрыть форму и вернуть результат.

Ответ 5

form.ShowDialog() показывает форму как модальный диалог. Это означает, что вызов не возвращается, пока форма не будет закрыта.
Обратите внимание, что щелчок по закрытию X в модальном диалоговом окне не закрывает форму, он просто скрывает ее. Я предполагаю, что это то, что смущает вас. Если вы хотите, чтобы код в форме1 продолжал выполнять, а не блокировал, вы должны вызвать Show() вместо ShowDialog(). Non-modal будет закрываться при нажатии X.

Если вам нужен блокирующий модальный диалог, вы должны окружить форму блоком использования, как описано в других ответах.
При создании модального диалога вы обычно добавляете кнопку "ОК" или аналогичную и устанавливаете свойство AcceptButton формы на эту кнопку, чтобы позволить пользователю закрыть форму, нажав клавишу ввода. Аналогичным образом вы можете добавить кнопку "Отмена" и установить свойство CancelButton для захвата клавиши Esc.
Добавьте обработчик кликов к двум кнопкам, соответствующим образом установите свойство DialogResult формы и вызовите Close().