关闭后处理表格

时间:2010-08-31 14:47:14

标签: c# winforms forms dispose

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

已编辑: 我的问题是:为什么在form2关闭后5秒后显示消息框!

5 个答案:

答案 0 :(得分:8)

编辑:这个问题原来是关于Dispose。

首先,Dispose注意垃圾收集。发生以下情况:

  1. 您有一个全局计时器实例
  2. 您创建form2
  3. Form2订阅计时器
  4. Form2已关闭和/或处置
  5. Timer事件触发,递增计数器并显示MessageBox
  6. Timer会一直触发,直到App关闭。
  7. 要理解的要点是,Close / Dispose只会更改Form的状态,他们不会(不能)'删除'实例。那么(封闭的)形式就在那里,计数器字段仍在那里并且事件触发。


    好的,第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;

答案 1 :(得分:4)

使用后处理Form的最简单,最可靠的方法是将用法放在使用块中

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

C#中的using块是一个构造,它基本上将上述内容扩展为以下代码。

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

答案 2 :(得分:3)

这是一个老问题,但它触及了一些关于对象如何工作的有趣观点。表格本质上是一个对象。同一类的所有对象共享相同的方法,但每个对象都有自己的数据。这是什么意思?这意味着,关闭或处置对象不会从内存中释放/删除/删除任何代码。只有数据。所有这些都是关于一般的对象,无论语言如何。

现在,特别是关于你的代码。让我们来看看Program.timer.Tick += timer_Tick;行的作用。这会在表单对象中为计时器对象提供指向函数的指针。所以,现在,无论你对表单对象做什么,计时器对象都将继续调用该函数。计时器对象不关心您的表单,甚至不知道Form对象的存在。它只关心你传递指针的函数。就计时器对象而言,此功能是一个独立的功能。

Form.Close()做什么? Form.Close()处理表单使用的资源,也就是说,标记表单的垃圾收集控件,除非使用ShowDialog显示表单。在这种情况下,必须手动调用Dispose()。 MSDN

不用说(或者可能不是那么不必要),如果关闭/处理表单从内存中清除了该函数,则计时器对象将具有无效指针,并且您的程序将在5秒后崩溃

答案 3 :(得分:1)

也许我正在读错的问题,但我认为先生们需要知道,要关闭一个以Form2.ShowDialog()打开的表单(比如form2),你需要在Form2中设置Form2.DialogResult。只需设置该成员就可以关闭表单并返回结果。

答案 4 :(得分:0)

form.ShowDialog()将表单显示为模式对话框。这意味着在表单关闭之前,调用不会返回 请注意,单击模式对话框上的关闭X不会关闭表单,它只是隐藏它。我猜这就是让你感到困惑的原因。 如果希望form1中的代码继续执行而不是阻塞,则应调用Show()而不是ShowDialog()。单击X时,非模态将关闭。

如果您确实需要阻止模式对话框,则应使用其他答案中所述的使用块来围绕表单。
在构建模态对话框时,通常会添加“确定”按钮或类似按钮,并将窗体的AcceptButton属性设置为该按钮,以允许用户通过按Enter来关闭窗体。同样,您可以添加“取消”按钮并设置CancelButton属性以捕获Esc键 为这两个按钮添加一个单击处理程序,相应地设置表单的DialogResult属性并调用Close()。