Andrew Rokicki
Andrew Rokicki

Reputation: 202

Stop long running events

I have a following form Form3 that is opened by another form Form1, and when closed Form1 opens back up.

The problem is when I close Form3 DoSomething keeps running after form is closed.

I understand that I can make DoSomething into a thread and set IsBackground = true but is there another way to stop all processes when form closes.

This code is just example, For illustration.

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

}

Upvotes: 2

Views: 333

Answers (5)

haithem khdimallah
haithem khdimallah

Reputation: 1

try to add this intsruction in the FormClosing event : System.Diagnostics.Process.GetCurrentProcess().Kill();

it's a little bit like this:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    System.Diagnostics.Process.GetCurrentProcess().Kill();
}

Upvotes: 0

Andrew Rokicki
Andrew Rokicki

Reputation: 202

Thanks to cdhowie suggestions and input of all others. Mowing DoEvents to the end and adding IsDipsosed solved my problem.

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

}

Upvotes: 0

Servy
Servy

Reputation: 203847

Your fundamental approach is flawed.

First off, Application.DoEvents should be avoided unless you are sure that you really need it, and that you are using it correctly. You do not need it here, and you are not using it correctly.

What you really need here is a 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();
}

When the Form is create the Timer is configured. The tick event is set, along with the interval. The tick event will look similar to your DoSomething method; it will involve running some bit of code every 10 seconds, from the UI thread, while keeping the UI responsive. When the form is closed simply stop the timer and it will stop firing off these events.

Also note that in this example here pressing the button multiple times simply resets the timer and the count, it doesn't end up creating two loops that each fire every 10 milliseconds.

Upvotes: 2

Sheridan Bulger
Sheridan Bulger

Reputation: 1214

You never break out of the while(true). You should either break the loop when it's IsDisposed is true, change your while loop to while(!IsDisposed), or store use a class level variable that determines when to break the loop.

I would probably opt for the latter, as it gives you a little more control.

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

}

Upvotes: 2

Dan Pichelman
Dan Pichelman

Reputation: 2332

Override this.Dispose() or this.Close() as appropriate and kill off DoSomething() manually.

Upvotes: 0

Related Questions