2010-08-31 22 views
11

Tengo el nuevo problema con abrir y cerrar forma en C#.Eliminar formulario después de cerrar

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

aquí es mi código:

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

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

+1

¿Por qué quiere deshacerse de los formularios antes de que el recolector de basura lo haga por usted (suponiendo que no haya referencias al formulario restante)? – Lazarus

+2

¿Qué significa "No funcionó"? ¿Se plantea una excepción? ¿La ventana no desaparece? @ Lazarus: Buena pregunta. – DHN

+0

[¿Tengo que deshacerme de un formulario después de cerrar el formulario?] (Https://stackoverflow.com/a/39501121/3110834) –

Respuesta

8

Editar: Esta pregunta se trata de Eliminar.

En primer lugar, Eliminar tiene que ver con la recolección de basura. Ocurre lo siguiente:

  1. tiene una instancia del temporizador mundial
  2. Se crea formulario2
  3. Form2 se suscribe al temporizador
  4. Form2 está cerrado y/o se han dispuesto
  5. desencadena el evento
  6. el temporizador, incrementa el contador y muestra un MessageBox
  7. El evento Timer sigue activando hasta que se cierra la aplicación.

El punto principal a entender es que Cerrar/Eliminar solo cambia el estado del Formulario, no lo hacen (no pueden) 'eliminar' la instancia. Entonces, la forma (cerrada) está allí, el campo del contador todavía está allí y el evento se dispara.


bien, parte 1:

Un bloque using() {} 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 
    } 

Si no es así, por favor 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 voy a asumir que es 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 evita que se disipe/cierre, por lo que su temporizador seguirá disparando para un formulario cerrado, y que generalmente fallará y causará otros problemas.

  1. No hacer esto (dar Form2 su propio temporizador)
  2. Uso un evento FormClosed darse de baja: Program.timer.Tick -= timer_Tick;
+2

+1 Para sugerir el uso de la declaración, podría querer darle un ejemplo. – jsmith

+0

Estimado Henk Holterman, eliminar el evento tic tick es la buena solución, pero mi pregunta es, ¿por qué el cuadro de mensaje muestra cuando el formulario se ha eliminado? – Mironline

+1

@Mironline: ¿Por qué no debería? Ni el Timer ni el MessageBox necesitan esa forma. Intenta establecer una propiedad Control en timer_Tick y tendrás una excepción. –

4

La forma más sencilla y fiable para disponer un Form después de usar es poner el uso en el interior de un bloque usando

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

el uso de bloque en C# es un constructo que esencialmente se expande lo anterior en el código siguiente.

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

en segundos, form2 tiene que inicializarse antes de acceder. y si se inicializa nunca es igual a nulo. Lo he intentado pero el cuadro de mensaje aparece después de 5 segundos. – Mironline

+0

esto solo funciona para formularios modales –

0

form.ShowDialog() muestra el formulario como un cuadro de diálogo modal. Esto significa que la llamada no regresa hasta que se cierra el formulario.
Tenga en cuenta que al hacer clic en Cerrar X en un cuadro de diálogo modal no se cierra el formulario, simplemente lo oculta. Supongo que esto es lo que te confunde. Si desea que el código en form1 continúe ejecutándose en lugar de bloquearse, debe llamar a Show() en lugar de ShowDialog(). No modal se cerrará cuando se haga clic en la X.

Si desea un cuadro de diálogo modal de bloqueo, debe rodear el formulario con un bloque de uso como se describe en las otras respuestas.
Al crear un cuadro de diálogo modal, normalmente agregará un botón "Aceptar" o similar y establecerá la propiedad AcceptButton del formulario en ese botón para permitir que el usuario cierre el formulario al presionar enter. De forma similar, puede agregar un botón "Cancelar" y establecer la propiedad CancelarBotón para capturar la tecla Esc.
Agregue un controlador de clic a los dos botones, configure la propiedad DialogResult del formulario en consecuencia y llame a Close().

1

Quizás estoy leyendo la pregunta incorrectamente, pero creo que los caballeros deben saber que, para cerrar un formulario (digamos formulario2) abierto como Form2.ShowDialog(), debe establecer Form2.DialogResult dentro de Form2. Solo establecer ese miembro es todo lo que se necesita para cerrar el formulario y devolver el resultado.

3

Esta es una pregunta antigua pero toca algunos puntos interesantes sobre cómo funcionan los objetos. Una forma es, esencialmente, un objeto. Todos los objetos de la misma clase comparten los mismos métodos, pero cada uno tiene sus propios datos. ¿Qué significa esto? Esto significa que cerrar o eliminar un objeto no libera/elimina/elimina ningún código de la memoria. Solo datos. Todo lo que se trataba de objetos en general, sin importar el idioma.

Ahora, específicamente sobre su código. Vamos a examinar lo que hace la línea Program.timer.Tick += timer_Tick;. Esto le da un puntero a su función en el objeto de formulario al objeto de temporizador . Entonces, ahora, no importa lo que haga con el objeto de formulario , el objeto de temporizador seguirá llamando a esa función. El objeto de temporizador no se preocupa por su formulario y ni siquiera es consciente de la existencia del objeto de formulario. Sólo le importa la función que pasó el puntero a. En lo que respecta al objeto del temporizador, esta función es independiente.

¿Qué hace Form.Close()? Form.Close() dispone los recursos utilizados por el formulario, es decir, marca los controles del formulario para la recolección de basura a menos que el formulario se muestre mediante ShowDialog. En ese caso, se debe llamar a Dispose() manualmente.MSDN

Ni que decir (o tal vez no tan innecesaria) que si el cierre/disponiendo la forma redondeada de la función de la memoria, el objeto de temporizador tendría un puntero no válido y el programa se accidente después de 5 segundos.

Cuestiones relacionadas