我在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秒后显示消息框!
编辑:这个问题原来是关于Dispose。
首先,Dispose注意垃圾收集。发生以下情况:
- 你有一个全局的Timer实例
- 你创建form2
- Form2订阅计时器
- Form2已关闭和/或处置
- Timer事件触发,递增计数器并显示MessageBox
- Timer事件会持续触发,直到App关闭。
要理解的要点是,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实例的引用,并且不会收集它。它不会阻止它被处置/关闭,因此您的计时器将继续触发已关闭的表单,这通常会失败并导致其他问题。
- 不要这样做(给Form2它自己的计时器)
- 使用FormClosed事件取消订阅:
Program.timer.Tick -= timer_Tick;
最简单,最可靠的处理方式 Form
使用之后是将用法放在使用块内
using (Form2 form = new Form2()) {
form.ShowDialog();
}
C#中的using块是一个构造,它基本上将上述内容扩展为以下代码。
Form2 form;
try {
form = new Form2();
...
} finally {
if ( form != null ) {
form.Dispose();
}
}
这是一个古老的问题,但它涉及一些关于对象如何工作的有趣点。表格本质上是一个对象。同一类的所有对象共享相同的方法,但每个对象都有自己的数据。这是什么意思?这意味着,关闭或处置对象不会释放/删除/删除任何对象 码 从记忆中。只有数据。所有这些都是关于一般的对象,无论语言如何。
现在,特别是关于你的代码。让我们来看看这条线 Program.timer.Tick += timer_Tick;
确实。这给出了一个指向你的函数的指针 表单对象 到了 计时器对象。那么,现在,不管你做了什么 表单对象, 计时器对象 将继续调用该功能。计时器对象 不关心你的表单,甚至不知道Form对象的存在。它只关心 您传递指针的函数。就计时器对象而言,此功能是一个独立的功能。
Form.Close()做什么? Form.Close()处理表单使用的资源,也就是说,标记表单的垃圾收集控件 除非表单使用ShowDialog显示。在这种情况下,必须手动调用Dispose()。 MSDN
不用说(或者可能不是那么不必要)如果关闭/处理表单从内存中清除了函数,那么计时器对象会有一个无效的指针,你的程序会 紧急 5秒后。
也许我正在读错的问题,但我认为先生需要知道,要关闭一个以Form2.ShowDialog()打开的表单(比如form2),你需要在Form2中设置Form2.DialogResult。只需设置该成员即可关闭表单并返回结果。
form.ShowDialog()将表单显示为模式对话框。这意味着在表单关闭之前,调用不会返回。
请注意,单击模式对话框上的关闭X不会关闭表单,它只是隐藏它。我猜这就是让你感到困惑的原因。
如果您希望form1中的代码继续执行而不是阻塞,则应调用Show()而不是ShowDialog()。单击X时,非模态将关闭。
如果您确实需要阻止模式对话框,则应使用其他答案中所述的使用块来围绕表单。
构建模式对话框时,通常会添加“确定”按钮或类似按钮,并将窗体的AcceptButton属性设置为该按钮,以允许用户通过按Enter键关闭窗体。同样,您可以添加“取消”按钮并设置CancelButton属性以捕获Esc键。
在这两个按钮上添加一个单击处理程序,相应地设置表单的DialogResult属性并调用Close()。