3 Replies - 2236 Views - Last Post: 20 September 2010 - 12:04 AM Rate Topic: -----

#1 bbonik  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 19-September 10

problem with 2Forms+progressbar+background worker

Posted 19 September 2010 - 01:52 AM

Dear all,
I am having a very frustrating problem with a project in Visual Studio 2008 C#. I have tried everything, I have searched everywhere, but it seems that nothing works. I would appreciate if someone gave me some directions or suggestions, as to where to look for the solution.
What I want to do:
I have 2 forms. The MAIN form, runs a heavy image processing algorithm, using a background worker. The second form, FORM2 must have a progress bar, which will display the progress of the image processing executed in MAIN form. It must also have a CANCEL button, which will allow the canceling of the image processing algorithm.

What I have done so far:
1. I have managed to solve the problem using only one form: there is no FORM2. The progress bar and the cancel button are on the MAIN form. Everything works fine. But this is not the thing I have to do! I really need the cancel button and the progress bar on a different form.
2. I have managed to show the progress bar on FORM2 running smoothly, but I cannot interact with FORM2 (the mouse pointer becomes a hourglass when I hover it over FORM2, thus, I cannot press the CANCEL or the X button).
In order to do that, I wrote the following code:

In MAIN form:

FORM2 PR = new FORM2();
PR.Show();                       
                        
for (i = 0; i < imsize_y; i++)
{
      //calculate the progress degree and store it in ‘Process’ variable

      PR.progressBar1.Value = Process;
      PR.Refresh(); //otherwise the PR form is not redrawn


      if (backgroundWorker1.CancellationPending   
      {
              PR.Close();//where the code stops in case cancel is pressed
              break;
      }

                           
      for (j = 0; j < imsize_x; j++)
      {
		//heavy image processing

      }
}

PR.Close();





3. I have also tried to use PR.ShowDialog() instead of PR.Show(),in order have focus on FORM2. However, in this case, the image processing stops until and I have to press something in FORM2 in order to proceed with the image processing in MAIN form.

I know that this has to do something with threading, but I don’t know what. When the MAIN form runs, I cannot interact with FORM2. I have found examples where I can communicate variables between forms, but, in these examples, there is no background worker involved.

I would appreciate any suggestions or directions, as to where to look for this solution.

Is This A Good Question/Topic? 0
  • +

Replies To: problem with 2Forms+progressbar+background worker

#2 FlashM  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 382
  • View blog
  • Posts: 1,195
  • Joined: 03-December 09

Re: problem with 2Forms+progressbar+background worker

Posted 19 September 2010 - 03:06 AM

Hope this helps... Read the code comments for more info...

Form1 - our main form
public partial class Form1 : Form
{
    //BackgroundWorker needs to be public so we can communicate
    //with from Form2
    public BackgroundWorker bw = new BackgroundWorker();

    //this variable just holds a reference to instantiated Form2
    //so that we're able to send progress info and update it's
    //progress bar
    private Form2 progressForm = null;

    public Form1()
    {
        InitializeComponent();
        bw.WorkerReportsProgress = true;
        bw.WorkerSupportsCancellation = true;
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        //Form2 constructor is extended so that it takes one input
        //parameter - in our case - a reference to Form1 (our main
        //form) so that we can communicate with BackgroundWorker
        if (progressForm == null)
                progressForm = new Form2(this);
        progressForm.Show();

        if (bw.IsBusy != true)
        {
            bw.RunWorkerAsync();
        }
    }

    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        for (int i = 1; i <= 100; i++)
        {
            if (worker.CancellationPending)
            {
                e.Cancel = true;
                break;
            }
            else
            {
                Thread.Sleep(100);
                worker.ReportProgress(i);
            }
        }
    }

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Cancelled)
        {
            //set progress bar on Form2 to zero
            this.progressForm.ProgressBarControl.Value = 0;
        }
        else if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
        }

        else
        {
            //set progress bar on Form2 to 100
            this.progressForm.ProgressBarControl.Value = 100;
        }

    }

    private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        //set progress bar on Form2 to e.ProgressPercentage value
        this.progressForm.ProgressBarControl.Value = e.ProgressPercentage;
    }

    private void button2_Click(object sender, EventArgs e)
    {
        if (bw.WorkerSupportsCancellation == true)
        {
            bw.CancelAsync();
        }
    }
}



Form2 - our progress bar form
public partial class Form2 : Form
{
    //private variable that holds a reference to our main form
    private Form1 m_mainForm;

    //extended Form2 constructor that accepts a reference to
    //our main form
    public Form2(Form1 mainForm)
    {
        InitializeComponent();
        m_mainForm = mainForm;
    }

    //public progress bar control getter and setter - so that
    //we are able to update it's progress value from main form
    public ProgressBar ProgressBarControl
    {
        get { return this.bw_progressBar; }
        set { this.bw_progressBar = value; }
    }

    //canceling the background worker on main form.
    //we wouldn't be able to cancel it if background worker
    //on main form is not public
    private void btnCancel_Click(object sender, EventArgs e)
    {
        if (m_mainForm.bw.WorkerSupportsCancellation == true)
        {
            m_mainForm.bw.CancelAsync();
        }
    }
}


This post has been edited by FlashM: 19 September 2010 - 03:11 AM

Was This Post Helpful? 3
  • +
  • -

#3 tlhIn`toq  Icon User is offline

  • Xamarin Cert. Dev.
  • member icon

Reputation: 6507
  • View blog
  • Posts: 14,372
  • Joined: 02-June 10

Re: problem with 2Forms+progressbar+background worker

Posted 19 September 2010 - 07:50 AM

FlashM: I think it is amazing that you did all that for the OP. Really nice. I +1'd ya for that.

bbonik: What wasn't really explained in all that was the concepts behind it. The short version is that it is BAD to directly change a control on one form from another. Each form should be a little black box that doesn't know anything about the other. You should raise events on form a saying "I'm done" and form b should react to that event with its own needs. Rather than form a having to tell form b, "now do this, and this, and change this."

These should help in more detail on the concepts behind what FlashM so generously provided.


Quick and easy custom events
Bulding an application - Part 1
Was This Post Helpful? 1
  • +
  • -

#4 bbonik  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 19-September 10

Re: problem with 2Forms+progressbar+background worker

Posted 20 September 2010 - 12:04 AM

Thank you very much all for your valuable help!

FlashM: Thank you a thousand times for your time and effort!
tlhIn'toq: Thank you very much for your guidelines!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1