Deseche el formulario después del cierre

Resuelto Mironline asked hace 14 años • 5 respuestas

Tengo el nuevo problema al abrir y cerrar formularios en C#.

Mi problema es cómo desechar el formulario después del cierre.

aquí está mi código:

Programa.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());
    }
}

Formulario1.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
    }
}

Formulario2.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("");
    }
}

Editado: Mi pregunta es: ¿por qué el cuadro de mensaje se muestra después de 5 segundos cuando el formulario 2 se ha cerrado?

Mironline avatar Aug 31 '10 21:08 Mironline
Aceptado

Esta pregunta resulta ser sobre Dispose.

En primer lugar, Dispose no tiene nada que ver con la recolección de basura. Sucede lo siguiente:

  1. Tienes una instancia de temporizador global
  2. Creas formulario2
  3. Form2 se suscribe al temporizador
  4. Form2 está cerrado y/o eliminado
  5. El evento Timer se activa, incrementa el contador y muestra un cuadro de mensaje.
  6. El evento del temporizador sigue funcionando hasta que se cierra la aplicación.

El punto principal a entender es que Cerrar/Desechar solo cambia el estado del Formulario, no (no pueden) "eliminar" la instancia. Entonces el formulario (cerrado) está ahí, el campo del contador todavía está ahí y el evento se activa.


Bien, parte 1:

Un using () {}bloque sería mejor pero esto debería funcionar:

    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
    }

En caso contrario, describa "no funciona".


    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
    }

Esto es extraño, pero asumiré que es un código artificial para la pregunta.

Su Program.Timer global ahora almacena una referencia a su instancia de Form2 y evitará que se recopile. No impide que se elimine/cierre, por lo que su temporizador seguirá funcionando para un formulario cerrado, y eso generalmente fallará y causará otros problemas.

  1. No hagas esto (dale a Form2 su propio temporizador)
  2. Utilice un evento FormClosed para cancelar la suscripción:Program.timer.Tick -= timer_Tick;
ℍ ℍ avatar Aug 31 '2010 14:08 ℍ ℍ

La forma más sencilla y confiable de eliminar el Formuso posterior es colocar el uso dentro de un bloque de uso.

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

El bloque de uso en C# es una construcción que esencialmente expande lo anterior al siguiente código.

Form2 form;
try {
  form = new Form2(); 
  ...
} finally {
  if ( form != null ) {
    form.Dispose();
  }
}
JaredPar avatar Aug 31 '2010 15:08 JaredPar