2

我有一个以下表单 Form3,它由另一个表单 Form1 打开,关闭时 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();
    }

}
4

5 回答 5

2

你永远不会摆脱这段时间(真的)。您应该在 IsDisposed 为真时中断循环,将您的 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();
    }

}
于 2012-10-03T15:57:04.147 回答
2

你的基本方法是有缺陷的。

首先,应避免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 毫秒触发一次。

于 2012-10-03T16:28:30.307 回答
0

覆盖this.Dispose()this.Close()酌情手动终止 DoSomething() 。

于 2012-10-03T15:54:36.657 回答
0

感谢 cdhowie 的建议和所有其他人的意见。将 DoEvents 修剪到最后并添加 IsDipsose 解决了我的问题。

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();
    }

}
于 2012-10-04T19:45:45.940 回答
0

尝试在 FormClosing 事件中添加此指令: System.Diagnostics.Process.GetCurrentProcess().Kill();

有点像这样:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    System.Diagnostics.Process.GetCurrentProcess().Kill();
}
于 2019-11-28T16:50:31.610 回答