2010-08-31 5 views
11

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

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

вот мой код:

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

Почему вы хотите избавиться от форм до того, как сборщик мусора сделает это за вас (при условии отсутствия ссылок на оставшуюся форму)? – Lazarus

+2

Что означает «Это не сработало»? Вызывается ли исключение? Не исчезает ли окно? @ Лазарус: Хороший вопрос. – DHN

+0

[Нужно ли удалять форму после того, как форма закрыта?] (Https://stackoverflow.com/a/39501121/3110834) –

ответ

8

Редактировать: Этот вопрос оказывается о Dispose.

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

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

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


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

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

+1 Для того, чтобы предлагать использование инструкции, возможно, захотите привести ему пример. – jsmith

+0

Уважаемый Хенк Холтерман, удалив событие таймера, это хорошее решение. Но мой вопрос: почему окно сообщения показывает, когда форма была удалена? – Mironline

+1

@Mironline: Почему бы и нет? Ни Timer, ни MessageBox не нуждаются в этой форме. Попробуйте установить свойство Control в timer_Tick, и у вас будет исключение. –

4

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

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

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

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

в секундах, форма 2 должна инициализироваться перед доступом. и если он инициализирован никогда не равен нулю. Я пробовал это, но окно сообщения отображается через 5 секунд. – Mironline

+0

это работает только для модальных форм –

0

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

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

1

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

3

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

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

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

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

Смежные вопросы