Microsoft Developer Network > Forums Home > Visual Studio Express Editions Forums > Visual C# Express Edition > How to update label text and pictureBox image from backgroundWorker_ProgressChanged?
Ask a questionAsk a question
 

AnswerHow to update label text and pictureBox image from backgroundWorker_ProgressChanged?

  • Saturday, June 07, 2008 2:04 AMMLyons10 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I have a backgroundWorker, and it works great, but I want to change the text of a label and the image in a pictureBox several times as the progress is changed.  The progressBar works fine.  I can't figure out how the best way to do this is though.  I can change the text of the label, but it appears I can do this only once?

    Any help is greatly appreciated.  I have attached my code, but have not written code for changing the image of the pictureBox, as I figured this would be done along with the label and it appears my timing is off or something...

    Code Snippet

            private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                ProgressBar1.Visible = true;
                ProgressBar1.Value = e.ProgressPercentage;

                if (Label2.Text == "Backing up Database...")
                {
                    Label2.Text = "Backing up Resources (Images, etc.)...";

                    return;

                }
                if (Label2.Text == "Backing up Resources (Images, etc.)...")
                {
                    Label2.Text = "Database and Resources Backed Up Successfully!";

                    return;

                }
            }



    Thanks Again,



Answers

  • Saturday, June 07, 2008 3:04 AMJohnWein Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Are you saying that the text "Database and Resources Backed Up Successfully!" is never displayed?  Does the event get fired more than once?  You should be able to change the PictureBox's image in a similar manner.

     

  • Wednesday, June 11, 2008 3:11 AMXun Ye Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    Hi MLyons10,

    As far as I know, the ProgressChanged event was raised by calling ReportProgress method of BackgroundWorker class in the DoWork event hander, a model like below.

    Code Snippet

    private}

    void InitializeBackgoundWorker()

            {

                backgroundWorker1.DoWork +=

                    new DoWorkEventHandler(backgroundWorker1_DoWork);

                backgroundWorker1.RunWorkerCompleted +=

                    new RunWorkerCompletedEventHandler(

                backgroundWorker1_RunWorkerCompleted);

                backgroundWorker1.ProgressChanged +=

                    new ProgressChangedEventHandler(

                backgroundWorker1_ProgressChanged);

            }

      private void backgroundWorker1_DoWork(object sender,

                DoWorkEventArgs e)

            {

    BackgroundWorker worker = sender as BackgroundWorker;

             // do the task

             // calling ReportProgress when percentage was changed

            Worker.ReportProgress(completed_percentage_of_task)

            }

    private void backgroundWorker1_RunWorkerCompleted(

                object sender, RunWorkerCompletedEventArgs e)

            {

             // do something when the task was completed

            }

     

           

            private void backgroundWorker1_ProgressChanged(object sender,

                ProgressChangedEventArgs e)

            {

            // to show the progress of the task in some controls

           

     

    In addition to the BackgroundWorker Class, please check the following LINK below.

    http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

    Regards,

    Xun

  • Wednesday, June 11, 2008 1:39 PMjannemanrobinson Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

     MLyons10 wrote:



    Code Snippet

            private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                ProgressBar1.Visible = true;
                ProgressBar1.Value = e.ProgressPercentage;

                if (Label2.Text == "Backing up Database...")
                {
                    Label2.Text = "Backing up Resources (Images, etc.)...";

                    return;

                }
                if (Label2.Text == "Backing up Resources (Images, etc.)...")
                {
                    Label2.Text = "Database and Resources Backed Up Successfully!";

                    return;

                }
            }




     

    throw in a couple of Application.DoEvents(); everytime you actually want to display something.

     

    Code Snippet

     private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                ProgressBar1.Visible = true;
                ProgressBar1.Value = e.ProgressPercentage;

                if (Label2.Text == "Backing up Database...")
                {
                    Label2.Text = "Backing up Resources (Images, etc.)...";

          Application.DoEvents();

                    return;

                }
                if (Label2.Text == "Backing up Resources (Images, etc.)...")
                {
                    Label2.Text = "Database and Resources Backed Up Successfully!";

                    Application.DoEvents();

                    return;

                }
            }

     

     

All Replies

  • Saturday, June 07, 2008 3:04 AMJohnWein Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Are you saying that the text "Database and Resources Backed Up Successfully!" is never displayed?  Does the event get fired more than once?  You should be able to change the PictureBox's image in a similar manner.

     

  • Wednesday, June 11, 2008 3:11 AMXun Ye Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    Hi MLyons10,

    As far as I know, the ProgressChanged event was raised by calling ReportProgress method of BackgroundWorker class in the DoWork event hander, a model like below.

    Code Snippet

    private}

    void InitializeBackgoundWorker()

            {

                backgroundWorker1.DoWork +=

                    new DoWorkEventHandler(backgroundWorker1_DoWork);

                backgroundWorker1.RunWorkerCompleted +=

                    new RunWorkerCompletedEventHandler(

                backgroundWorker1_RunWorkerCompleted);

                backgroundWorker1.ProgressChanged +=

                    new ProgressChangedEventHandler(

                backgroundWorker1_ProgressChanged);

            }

      private void backgroundWorker1_DoWork(object sender,

                DoWorkEventArgs e)

            {

    BackgroundWorker worker = sender as BackgroundWorker;

             // do the task

             // calling ReportProgress when percentage was changed

            Worker.ReportProgress(completed_percentage_of_task)

            }

    private void backgroundWorker1_RunWorkerCompleted(

                object sender, RunWorkerCompletedEventArgs e)

            {

             // do something when the task was completed

            }

     

           

            private void backgroundWorker1_ProgressChanged(object sender,

                ProgressChangedEventArgs e)

            {

            // to show the progress of the task in some controls

           

     

    In addition to the BackgroundWorker Class, please check the following LINK below.

    http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

    Regards,

    Xun

  • Wednesday, June 11, 2008 1:39 PMjannemanrobinson Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

     MLyons10 wrote:



    Code Snippet

            private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                ProgressBar1.Visible = true;
                ProgressBar1.Value = e.ProgressPercentage;

                if (Label2.Text == "Backing up Database...")
                {
                    Label2.Text = "Backing up Resources (Images, etc.)...";

                    return;

                }
                if (Label2.Text == "Backing up Resources (Images, etc.)...")
                {
                    Label2.Text = "Database and Resources Backed Up Successfully!";

                    return;

                }
            }




     

    throw in a couple of Application.DoEvents(); everytime you actually want to display something.

     

    Code Snippet

     private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                ProgressBar1.Visible = true;
                ProgressBar1.Value = e.ProgressPercentage;

                if (Label2.Text == "Backing up Database...")
                {
                    Label2.Text = "Backing up Resources (Images, etc.)...";

          Application.DoEvents();

                    return;

                }
                if (Label2.Text == "Backing up Resources (Images, etc.)...")
                {
                    Label2.Text = "Database and Resources Backed Up Successfully!";

                    Application.DoEvents();

                    return;

                }
            }

     

     

  • Sunday, June 15, 2008 8:58 PMMLyons10 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Thank you all very much for your help.  I made use of all of these great suggestions.

    Thanks Again,
  • Thursday, November 05, 2009 7:56 AMZeeshan Jan Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Hello ,

     I have a very similar problem which you are facing. I have two forms. One form contains the button on the click of this button , I display another form which contains the progress bar control. I have also used the Backgroundworker similar to you.
    on the click of the button of the main form , the another form is displayed but I get the error Cross-thread operation not valid: Control  accessed from a thread other than the thread it was created on, this error comes on this method:

     

     

            private void BackgroundWorker_ProgressChanged(object sender,ProgressChangedEventArgs e)
            {
                //orderProgressBar.Invoke(new ProgressInvoker(orderProgressBar.PerformStep), e.ProgressPercentage);
                orderProgressBar.progressBarCtl.Value = e.ProgressPercentage;
            }

    I have also used the commented line of code this does not give any error , but the progress bar does not get updated.


    zeeshan [ visit my forum: www.code4project.com ]
  • Thursday, November 05, 2009 10:57 AMDheeraj_Mallemala Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Hello,

    i think below code should work. i have used couple of .net 3.5 features.


    delegate void SetConversionProgressEvantHandler(object sender, ProgressChangedEventArgs e)

    private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)

    {
            SetConversionProgressEvantHandler delegatObject;


             if (orderProgressBar.progressBarCtl.InvokeRequired) 
             {
                      //SetConversionProgressEvantHandler delegatObject = 
                      //new SetProgressEvantHandler(this.BackgroundWorker_ProgressChanged);

                      //don't need above code, just assigning the method to delegate will do. New feature of .Net 3.5
                      delegatObject = this.BackgroundWorker_ProgressChanged;

                      this.Invoke(delegatObject, new object[] { sender, e }); //New feature of .Net 3.5

              } 
              else

              {

                        orderProgressBar.progressBarCtl.value = e.ProgressPercentage;

              }

    }

  • Thursday, November 05, 2009 6:20 PMRudedog2 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Hello ,

     I have a very similar problem which you are facing. I have two forms. One form contains the button on the click of this button , I display another form which contains the progress bar control. I have also used the Backgroundworker similar to you.
    on the click of the button of the main form , the another form is displayed but I get the error Cross-thread operation not valid: Control  accessed from a thread other than the thread it was created on, this error comes on this method:

     

     

            private void BackgroundWorker_ProgressChanged(object sender,ProgressChangedEventArgs e)
            {
                //orderProgressBar.Invoke(new ProgressInvoker(orderProgressBar.PerformStep), e.ProgressPercentage);
                orderProgressBar.progressBarCtl.Value = e.ProgressPercentage;
            }

    I have also used the commented line of code this does not give any error , but the progress bar does not get updated.


    zeeshan [ visit my forum: www.code4project.com ]


    Please start a new thread for your question.
    We do not want the person who started this thread to get email alerts about someone else's problem.

    Mark the best replies as answers. "Fooling computers since 1971."
  • Friday, November 06, 2009 10:21 AMDheeraj_Mallemala Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    when ever you get a "Cross-thread operation not valid" error, check "InvokeRequired" property of the control.  and use delegate and raise a event. as posted above.
  • Friday, November 06, 2009 2:33 PMRudedog2 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    when ever you get a " Cross-thread operation not valid" error, check "InvokeRequired" property of the control.  and use delegate and raise a event. as posted above.



    Not recommended with a BackgroundWorker , which should not be regarded as a typicial 'thread' even though it may behave like one.  Call the worker.ReportProgess method on the worker instance, so that all updates can be performed directly on the UI thread as they should  be.

    The mechanism to raise an event is already built into the BGW.  Just call ReportProgress and worker.ProgressChanged is raised on the UI thread.  It even allows you to 'marshal' an object back to the UI thread.  Easy.

    Mark the best replies as answers. "Fooling computers since 1971."
  • Friday, November 06, 2009 2:41 PMRudedog2 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    If you need to update other classes about the progress of the BGW, then simply add an event to your class and let subscribers listen for events is they wish.  Here's a sample form.  I commented the worker_ProgressChanged event handler for you.  The class is a complete form.

    To use this form, add a class file to your project, not a form. 
    Copy the entire contents into the new class file.



     public partial class DWGDemoForm : Form
        {
            BackgroundWorker worker;
            private Button btnPause;
            private bool workerPaused;

            int workerData;

            public DWGDemoForm()
            {
                InitializeComponent();
            }

            private Button btnStart;
            private Button btnStop;
            private ProgressBar progressBar1;
            private Label label1;
            private Label label2;
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.IContainer components = null;

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }

            #region Windows Form Designer generated code

            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                this.btnStart = new System.Windows.Forms.Button();
                this.btnStop = new System.Windows.Forms.Button();
                this.progressBar1 = new System.Windows.Forms.ProgressBar();
                this.label1 = new System.Windows.Forms.Label();
                this.label2 = new System.Windows.Forms.Label();
                this.btnPause = new System.Windows.Forms.Button();
                this.SuspendLayout();
                //
                // btnStart
                //
                this.btnStart.Location = new System.Drawing.Point(76, 94);
                this.btnStart.Name = "btnStart";
                this.btnStart.Size = new System.Drawing.Size(75, 23);
                this.btnStart.TabIndex = 0;
                this.btnStart.Text = "Start";
                this.btnStart.UseVisualStyleBackColor = true;
                this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
                //
                // btnStop
                //
                this.btnStop.Location = new System.Drawing.Point(239, 93);
                this.btnStop.Name = "btnStop";
                this.btnStop.Size = new System.Drawing.Size(75, 23);
                this.btnStop.TabIndex = 1;
                this.btnStop.Text = "Stop";
                this.btnStop.UseVisualStyleBackColor = true;
                this.btnStop.Click += new System.EventHandler(this.btnStop_Click);
                //
                // progressBar1
                //
                this.progressBar1.Location = new System.Drawing.Point(76, 65);
                this.progressBar1.Name = "progressBar1";
                this.progressBar1.Size = new System.Drawing.Size(238, 23);
                this.progressBar1.TabIndex = 2;
                //
                // label1
                //
                this.label1.AutoSize = true;
                this.label1.Location = new System.Drawing.Point(174, 72);
                this.label1.Name = "label1";
                this.label1.Size = new System.Drawing.Size(35, 13);
                this.label1.TabIndex = 3;
                this.label1.Text = "label1";
                //
                // label2
                //
                this.label2.AutoSize = true;
                this.label2.Location = new System.Drawing.Point(96, 40);
                this.label2.Name = "label2";
                this.label2.Size = new System.Drawing.Size(35, 13);
                this.label2.TabIndex = 4;
                this.label2.Text = "label2";
                //
                // btnPause
                //
                this.btnPause.Location = new System.Drawing.Point(158, 93);
                this.btnPause.Name = "btnPause";
                this.btnPause.Size = new System.Drawing.Size(75, 23);
                this.btnPause.TabIndex = 5;
                this.btnPause.Text = "Pause";
                this.btnPause.UseVisualStyleBackColor = true;
                this.btnPause.Click += new System.EventHandler(this.btnPause_Click);
                //
                // DWGDemoForm
                //
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(376, 196);
                this.Controls.Add(this.btnPause);
                this.Controls.Add(this.label2);
                this.Controls.Add(this.label1);
                this.Controls.Add(this.progressBar1);
                this.Controls.Add(this.btnStop);
                this.Controls.Add(this.btnStart);
                this.Name = "DWGDemoForm";
                this.Text = "DWGDemoForm";
                this.Load += new System.EventHandler(this.Form_Load);
                this.ResumeLayout(false);
                this.PerformLayout();

            }

            #endregion


            private void Form_Load(object sender, EventArgs e)
            {
                this.workerPaused = false;
                //
                this.btnStop.Enabled = false;
                this.btnPause.Enabled = false;
                //
                this.label1.Text = "";
                this.label1.Visible = false;
                //
                this.label2.Text = "No Progress To Report.";
                //
                this.progressBar1.Step = 1;
                this.progressBar1.Maximum = 100;
                this.progressBar1.Minimum = 0;
                this.progressBar1.Style = ProgressBarStyle.Continuous;
                //
                InitializeBGW();
                return;

            }

            private void InitializeBGW()
            {
                this.worker = null;
                this.worker = new BackgroundWorker();
                this.worker.WorkerReportsProgress = true;
                this.worker.WorkerSupportsCancellation = true;
                this.worker.DoWork +=
                    new DoWorkEventHandler(worker_DoWork);
                this.worker.ProgressChanged +=
                    new ProgressChangedEventHandler(worker_ProgressChanged);
                this.worker.RunWorkerCompleted +=
                    new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                this.worker.Disposed += new EventHandler(worker_Disposed);
                //
            }

            private void btnStart_Click(object sender, EventArgs e)
            {
                this.InitializeBGW();
                this.label1.Visible = true;
                this.btnStop.Enabled = true;
                this.btnPause.Enabled = true;
                this.btnStart.Enabled = false;
                this.workerPaused = false;
                this.worker.RunWorkerAsync(this.workerData);
            }

            private void btnStop_Click(object sender, EventArgs e)
            {
                this.btnStop.Enabled = false;
                this.btnPause.Enabled = false;
                this.btnStart.Enabled = true;
                this.worker.CancelAsync();
                this.workerData = 0;
                this.progressBar1.Value = this.workerData;
            }
          
            private void btnPause_Click(object sender, EventArgs e)
            {
                this.workerPaused = true;
                this.btnStop.Enabled = true;
                this.btnPause.Enabled = false;
                this.btnStart.Enabled = true;
                this.worker.CancelAsync();
            }

            void worker_DoWork(object sender, DoWorkEventArgs e)
            {
                DoTheWork(e);
            }

            private void DoTheWork(DoWorkEventArgs e)
            {
                int startPosition = (int)e.Argument;
                for (int i = startPosition; i < 100; i++)
                {
                    System.Threading.Thread.Sleep(90);
                    worker.ReportProgress(i, "Background Worker Is In Progress ...");
                    if (worker.CancellationPending)
                    {
                        e.Cancel = true;  // exiting the loop properly,
                        i = 100;  // calling return here can throw future exceptions
                    }
                }
                return;
            }

            void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                this.workerData = e.ProgressPercentage;
                string progressReport = (string)e.UserState;
                this.progressBar1.Value = this.workerData;
                this.label1.Text = this.progressBar1.Value.ToString();
                this.label2.Text = progressReport;
                //
                // fire an event in this class to notify other class
                //
                return;
            }

            void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {

                if (e.Error != null)
                {
                    this.label2.Text = "An error was encountered.";
                }
                else
                {
                    if (e.Cancelled)
                    {
                        if (this.workerPaused)
                        {
                            this.label2.Text = "The work was paused by the user.";
                            this.workerPaused = false;
                        }
                        else
                        {
                            this.label2.Text = "The work was cancelled by the user.";
                            this.workerData = 0;
                            this.progressBar1.Value = this.workerData;
                        }
                    }
                    else
                    {
                        this.label1.Visible = false;
                        this.progressBar1.Value = this.progressBar1.Minimum;
                        this.label2.Text = "Work has been completed.";
                        this.workerData = 0;
                        this.btnStop.Enabled = false;
                        this.btnPause.Enabled = false;
                        this.btnStart.Enabled = true;
                    }
                }
                this.worker.Dispose();  // Dispose of the object, do not re-use.

                return;
            }

            void worker_Disposed(object sender, EventArgs e)
            {
                //if (worker == null)
                //{
                //    Debug.WriteLine("Worker has not been disposed");
                //}
                //else
                //{
                //    Debug.WriteLine("Worker has been disposed");
                //}
                return;
            }

        }

    Mark the best replies as answers. "Fooling computers since 1971."
  • Monday, November 09, 2009 3:02 AMZeeshan Jan Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hey Guys,
      I have solved the problem. The problem was very interesting , as when I clicked on the button to load my new for at that time the progress bar on the new form was getting initialized and when I run the Background worker and it tries to access the progress bar , I used to get the error because the progress bar was initialized in the initial thread. Them I thought why not just put the code to initialize the progress bar before I cal lthe Background worker .RunAsync method , and it worked !!!!
      Thanx everyone for replying and making me reach to the solution.
    zeeshan [ visit my forum: www.code4project.com ]