关闭后处理表格

Posted

技术标签:

【中文标题】关闭后处理表格【英文标题】:Dispose form after closing 【发布时间】:2011-04-06 07:49:38 【问题描述】:

我遇到了在 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());
    

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秒后显示消息框!

【问题讨论】:

为什么要在垃圾收集器为您执行此操作之前处理表单(假设没有对剩余表单的引用)? “它不起作用”是什么意思?是否引发异常?窗口不会消失吗? @Lazarus:好问题。 Do I need to Dispose a Form after the Form got Closed? 【参考方案1】:

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

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

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

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

【讨论】:

【参考方案2】:

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

【讨论】:

【参考方案3】:

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

首先,Dispose 与垃圾收集有关。会发生以下情况:

    您有一个全局 Timer 实例 您创建 form2 Form2 订阅定时器 Form2 已关闭和/或处置 Timer 事件触发,计数器递增并显示 MessageBox Timer 事件一直触发,直到应用程序关闭。

要理解的要点是 Close/Dispose 仅​​更改表单的状态,它们不会(不能)“删除”实例。所以(关闭的)表单在那里,计数器字段仍然在那里并且事件触发。


好的,第 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 实例的引用,并将防止它被收集。它不会阻止它被处置/关闭,因此您的计时器将继续为已关闭的表单触发,这通常会失败并导致其他问题。

    不要这样做(给 Form2 自己的计时器) 使用 FormClosed 事件取消订阅:Program.timer.Tick -= timer_Tick;

【讨论】:

+1 建议使用using语句,不妨举个例子。 亲爱的 Henk Holterman,删除计时器滴答事件是一个很好的解决方案,但我的问题是,为什么在表单处理完毕后会显示消息框? @Mironline:为什么不应该呢? Timer 和 MessageBox 都不需要这种形式。尝试在 timer_Tick 中设置一个 Control 属性会出现异常。【参考方案4】:

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

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

【讨论】:

【参考方案5】:

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

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

C# 中的 using 块本质上是将上面的代码扩展为下面的代码。

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

【讨论】:

以秒为单位,form2 必须在访问之前进行初始化。如果它初始化永远不等于null。我试过了,但消息框会在 5 秒后显示。

以上是关于关闭后处理表格的主要内容,如果未能解决你的问题,请参考以下文章

模式不会关闭 ajax 成功

运行批处理文件后如何关闭命令行窗口?

如何让批处理命令后运行后自动关闭

iOS 通知:WhatsApp 在强制关闭后如何接收通知和处理?

批处理 自动输入Y和 允许后自动关闭

windows批处理 打开exe后关闭cmd