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

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

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

вот мой код:

Программа.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());
    }
}

Форма1.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
    }
}

Форма2.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 закрыта!


person Mironline    schedule 31.08.2010    source источник
comment
Почему вы хотите избавиться от форм до того, как сборщик мусора сделает это за вас (при условии, что на форму не осталось ссылок)?   -  person Lazarus    schedule 31.08.2010
comment
Что значит это не сработало? Возникает ли исключение? Окно не исчезает? @Lazarus: Хороший вопрос.   -  person DHN    schedule 31.08.2010
comment
Нужно ли удалять форму после закрытия формы?   -  person Reza Aghaei    schedule 04.12.2017


Ответы (5)


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

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

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

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


Хорошо, часть 1:

Блок 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 и предотвращает его сбор. Это не мешает ему быть удаленным/закрытым, поэтому ваш таймер будет продолжать срабатывать для закрытой формы, и это обычно не работает и вызывает другие проблемы.

  1. Не делайте этого (дайте Form2 собственный таймер)
  2. Используйте событие FormClosed для отмены подписки: Program.timer.Tick -= timer_Tick;
person Henk Holterman    schedule 31.08.2010
comment
+1 За предложение использовать утверждение, возможно, вы захотите привести ему пример. - person jsmith; 31.08.2010
comment
Уважаемый Хенк Холтерман, удаление события таймера является хорошим решением, но мой вопрос: почему окно сообщения отображается, когда форма утилизирована? - person Mironline; 31.08.2010
comment
@Mironline: Почему бы и нет? Ни Timer, ни MessageBox не нуждаются в этой форме. Попробуйте установить свойство Control в timer_Tick, и вы получите исключение. - person Henk Holterman; 31.08.2010

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

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

Блок using в C# — это конструкция, которая существенно расширяет приведенный выше код в следующий код.

Form2 form;
try {
  form = new Form2(); 
  ...
} finally {
  if ( form != null ) {
    form.Dispose();
  }
}
person JaredPar    schedule 31.08.2010
comment
в блоке секунд форма2 должна инициализироваться перед доступом. и если он инициализирован, никогда не равен нулю. Я пробовал это, но окно сообщения появляется через 5 секунд. - person Mironline; 31.08.2010

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

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

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

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

person ThunderGr    schedule 02.11.2013

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

person Snowpaque    schedule 22.10.2012

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

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

person Holstebroe    schedule 31.08.2010