How can a new Form be run on a different thread in C#?

SLp picture SLp · Aug 14, 2010 · Viewed 29.8k times · Source

I'm just trying to run a new thread each time a button click even occurs which should create a new form. I tried this in the button click event in the MainForm:

private void button1_Click(object sender, EventArgs e)
{
    worker1 = new Thread(new ThreadStart(thread1));
    worker2 = new Thread(new ThreadStart(thread2));

    worker1.Start();
    worker2.Start();
}

private void thread1()
{
    SubForm s = new SubForm();
    s.Show();
}

private void thread2()
{
    SubForm s = new SubForm();
    s.Show();
}

The code in the Subform button click event goes like this:

private void button1_Click(object sender, EventArgs e)
{
    int max;
    try
    {
        max = Convert.ToInt32(textBox1.Text);
    }
    catch
    {
        MessageBox.Show("Enter numbers", "ERROR");
        return;
    }

    progressBar1.Maximum = max;

    for ( long i = 0; i < max; i++)
    {
        progressBar1.Value = Convert.ToInt32(i);
    }          
}

Is this the right way? Because I'm trying to open two independent forms, operations in one thread should not affect the other thread.

Or is BackGroundworker the solution to implement this? If yes, can anyone please help me with that?

Answer

Timwi picture Timwi · Aug 14, 2010

You do not need to run forms in separate threads. You can just call s.Show() on multiple forms normally. They will not block each other.

Of course, if you’re doing something else, like some sort of calculation or other task that takes a long while, then you should run that in a separate thread, but not the form.

Here is a bit of code that will let you create a progress bar that shows progress for a long process. Notice that every time to access the form from inside the thread, you have to use .Invoke(), which actually schedules that invocation to run on the GUI thread when it’s ready.

public void StartLongProcess()
{
    // Create and show the form with the progress bar
    var progressForm = new Subform();
    progressForm.Show();
    bool interrupt = false;

    // Run the calculation in a separate thread
    var thread = new Thread(() =>
    {
        // Do some calculation, presumably in some sort of loop...
        while ( ... )
        {
            // Every time you want to update the progress bar:
            progressForm.Invoke(new Action(
                () => { progressForm.ProgressBar.Value = ...; }));

            // If you’re ready to cancel the calculation:
            if (interrupt)
                break;
        }

        // The calculation is finished — close the progress form
        progressForm.Invoke(new Action(() => { progressForm.Close(); }));
    });
    thread.Start();

    // Allow the user to cancel the calculation with a Cancel button
    progressForm.CancelButton.Click += (s, e) => { interrupt = true; };
}