代码之家  ›  专栏  ›  技术社区  ›  Mironline Naeem Bashir

关闭后处理窗体

  •  12
  • Mironline Naeem Bashir  · 技术社区  · 14 年前

    我在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已关闭!

    5 回复  |  直到 11 年前
        1
  •  9
  •   Henk Holterman    14 年前

    编辑:这个问题原来是关于处置的。

    1. 您有一个全局计时器实例
    2. 你创建了form2
    3. Form2订阅计时器
    4. 表格2已关闭和/或处理
    5. 计时器事件一直启动,直到应用程序关闭。


    A 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
        }
    

    您的全球程序定时器现在存储对您的Form2实例的引用,并防止它被收集。它不会阻止它被释放/关闭,因此您的计时器将继续为关闭的窗体触发,而这通常会失败并导致其他问题。

    1. 不要这样做(给Form2它自己的计时器)
    2. 使用FormClosed事件取消订阅: Program.timer.Tick -= timer_Tick;
        2
  •  4
  •   JaredPar    14 年前

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

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

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

    Form2 form;
    try {
      form = new Form2(); 
      ...
    } finally {
      if ( form != null ) {
        form.Dispose();
      }
    }
    
        3
  •  3
  •   ThunderGr    11 年前

    这是一个老问题,但它涉及到一些有趣的问题,即对象如何工作。形式本质上是一个对象。同一类的所有对象共享相同的方法,但每个对象都有自己的数据。这是什么意思?这意味着,关闭或处理对象不会释放/删除/移除任何对象 代码 从记忆中。只有数据。所有这些都是关于物体的,不管是什么语言。

    现在,特别是关于你的代码。让我们看看这条线是什么 Program.timer.Tick += timer_Tick; 做。这将在 窗体对象 . 所以,现在,不管你对 ,的 计时器对象 将继续调用该函数。计时器对象 不关心你的形式,甚至不知道形式对象的存在 . 它只关心 将指针传递到的函数 . 就计时器对象而言,此函数是一个独立函数。

    表单将使用ShowDialog显示。在这种情况下,必须手动调用Dispose()。 MSDN

    不必说(或者也许不是那么不必要),如果关闭/处理窗体将函数从内存中清除,那么timer对象将有一个无效指针,而您的程序将 崩溃

        4
  •  1
  •   Snowpaque    12 年前

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

        5
  •  0
  •   Holstebroe    14 年前

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

    如果您确实想要一个阻塞模式对话框,您应该用一个using块包围窗体,如其他答案中所述。

    向这两个按钮添加一个click处理程序,相应地设置窗体的DialogResult属性并调用Close()。