我在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秒后显示消息框!
答案 0 :(得分:8)
编辑:这个问题原来是关于Dispose。
首先,Dispose注意垃圾收集。发生以下情况:
要理解的要点是,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实例的引用,并且不会被收集。它不会阻止它被处置/关闭,所以你的计时器将继续触发一个封闭的表格,这通常会失败并导致其他问题。
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()。