[英]Stop long running events
我有一个由另一个表单 Form1 打开的以下表单 Form3,当关闭 Form1 时,它会重新打开。
问题是当我关闭 Form3 时,DoSomething 在表单关闭后继续运行。
我知道我可以将 DoSomething 变成一个线程并设置 IsBackground = true 但还有另一种方法可以在表单关闭时停止所有进程。
此代码只是示例,用于说明。
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void DoSomething()
{
int i = 0;
while(true)
{
if (!this.IsDisposed)
{
Application.DoEvents();
i++;
Thread.Sleep(10);
label1.Text = i.ToString();
dataGridView1.Rows.Add();
}
}
}
private void button1_Click(object sender, EventArgs e)
{
DoSomething();
}
private void Form3_FormClosed(object sender, FormClosedEventArgs e)
{
this.Dispose();
Form1.Default.Show();
}
}
你永远不会突破 while(true)。 您应该在 IsDisposed 为 true 时中断循环,将 while 循环更改为 while(!IsDisposed),或者存储使用确定何时中断循环的类级别变量。
我可能会选择后者,因为它给了你更多的控制权。
public partial class Form3 : Form
{
volatile bool clDoSomething;
public Form3()
{
InitializeComponent();
}
private void DoSomething()
{
int i = 0;
clDoSomething = true;
while(clDoSomething)
{
Application.DoEvents();
++i;
Thread.Sleep(10);
label1.Text = i.ToString();
dataGridView1.Rows.Add();
}
}
private void button1_Click(object sender, EventArgs e)
{
DoSomething();
}
private void Form3_FormClosed(object sender, FormClosedEventArgs e)
{
clDoSomething = false;
Form1.Default.Show();
}
}
你的基本方法有缺陷。
首先,应避免使用Application.DoEvents,除非您确定确实需要它并且正确使用它。 您在这里不需要它,并且您没有正确使用它。
你真正需要的是一个Timer
。
private Timer timer = new Timer();
private int count = 0;
public Form3()
{
InitializeComponent();
timer.Tick += timer_Tick;
timer.Interval = 10;
//when the form is closed stop the timer.
FormClosed += (_, args) => timer.Stop();
}
private void button1_Click(object sender, EventArgs e)
{
count = 0;
timer.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
count++;
label1.Text = count.ToString();
dataGridView1.Rows.Add();
}
创建Form
时,配置Timer
。 滴答事件与间隔一起设置。 滴答事件看起来类似于你的DoSomething
方法; 它将涉及每 10 秒从 UI 线程运行一些代码,同时保持 UI 响应。 当表单关闭时,只需停止计时器,它将停止触发这些事件。
另请注意,在此示例中,多次按下按钮只会重置计时器和计数,它最终不会创建两个循环,每个循环每 10 毫秒触发一次。
根据需要覆盖this.Dispose()
或this.Close()
并手动this.Close()
DoSomething() 。
感谢 cdhowie 的建议和所有其他人的投入。 将 DoEvents 修剪到最后并添加 IsDipsosed 解决了我的问题。
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void DoSomething()
{
int i = 0;
while ((true) && !this.IsDisposed)
{
i++;
Thread.Sleep(10);
label1.Text = i.ToString();
dataGridView1.Rows.Add();
Application.DoEvents();
}
}
private void button1_Click(object sender, EventArgs e)
{
DoSomething();
}
private void Form3_FormClosed(object sender, FormClosedEventArgs e)
{
Form1.Default.Show();
}
}
尝试在 FormClosing 事件中添加此指令: System.Diagnostics.Process.GetCurrentProcess().Kill();
有点像这样:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
System.Diagnostics.Process.GetCurrentProcess().Kill();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.