Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Background worker with progress bar timing issue

Background worker with progress bar timing issue

Scheduled Pinned Locked Moved C#
helpquestion
6 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    Blubbo
    wrote on last edited by
    #1

    I've come across with this progress bar using worker.ReportProgress(). I was hoping to get a real-time progress Bar value from outside Write_Tag method. In this code below, it does seem to have some 1-2 seconds delay before showing the progress bar status. Any suggesion?

    private void InitializeProgressBars()
    {
    for (int i = 0; i < DevicePath.Count; i++)
    {
    progressBar[i] = new ProgressBar();
    progressBar[i].Location = new Point(3, 16);
    progressBar[i].Size = new Size(605, 31);
    progressBar[i].Maximum = 100;
    }

    gbProgressStatus0.Controls.Add(progressBar\[0\]);
    gbProgressStatus1.Controls.Add(progressBar\[1\]);
    gbProgressStatus2.Controls.Add(progressBar\[2\]);
    gbProgressStatus3.Controls.Add(progressBar\[3\]);
    

    }

    private void InitializeBackgroundWorkers()
    {
    for (var f = 0; f < DevicePath.Count; f++)
    {
    bw[f] = new BackgroundWorker();
    bw[f].WorkerReportsProgress = true;
    bw[f].WorkerSupportsCancellation = true;

       switch (f)
       {
          case 0:
          {
              bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork0);
              bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted0);
              break;
          }
          case 1:
          {
              bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork1);
              bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted1);
              break;
          }
          case 2:
          {
              bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork2);
              bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted2);
              break;
           }
           case 3:
           {
              bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork3);
              bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted3);
              break;
           }
        }
     }
    
     bw\[0\].ProgressChanged += (sender, e) => { progressBar\[0\].Value = e.ProgressPercentage; };
     bw\[1\].ProgressChanged += (sender, e) => { progressBar\[1\].Value = e.ProgressPercentage; };
     bw\[2\].ProgressChanged += (sender, e) => { progressBar\[2\].Value = e.ProgressPercentage; };
     bw\[3\].ProgressChanged += (sender, e) => { progressBar\[3\].Value = e.ProgressPercent
    
    L M 2 Replies Last reply
    0
    • B Blubbo

      I've come across with this progress bar using worker.ReportProgress(). I was hoping to get a real-time progress Bar value from outside Write_Tag method. In this code below, it does seem to have some 1-2 seconds delay before showing the progress bar status. Any suggesion?

      private void InitializeProgressBars()
      {
      for (int i = 0; i < DevicePath.Count; i++)
      {
      progressBar[i] = new ProgressBar();
      progressBar[i].Location = new Point(3, 16);
      progressBar[i].Size = new Size(605, 31);
      progressBar[i].Maximum = 100;
      }

      gbProgressStatus0.Controls.Add(progressBar\[0\]);
      gbProgressStatus1.Controls.Add(progressBar\[1\]);
      gbProgressStatus2.Controls.Add(progressBar\[2\]);
      gbProgressStatus3.Controls.Add(progressBar\[3\]);
      

      }

      private void InitializeBackgroundWorkers()
      {
      for (var f = 0; f < DevicePath.Count; f++)
      {
      bw[f] = new BackgroundWorker();
      bw[f].WorkerReportsProgress = true;
      bw[f].WorkerSupportsCancellation = true;

         switch (f)
         {
            case 0:
            {
                bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork0);
                bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted0);
                break;
            }
            case 1:
            {
                bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork1);
                bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted1);
                break;
            }
            case 2:
            {
                bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork2);
                bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted2);
                break;
             }
             case 3:
             {
                bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork3);
                bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted3);
                break;
             }
          }
       }
      
       bw\[0\].ProgressChanged += (sender, e) => { progressBar\[0\].Value = e.ProgressPercentage; };
       bw\[1\].ProgressChanged += (sender, e) => { progressBar\[1\].Value = e.ProgressPercentage; };
       bw\[2\].ProgressChanged += (sender, e) => { progressBar\[2\].Value = e.ProgressPercentage; };
       bw\[3\].ProgressChanged += (sender, e) => { progressBar\[3\].Value = e.ProgressPercent
      
      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      Blubbo wrote:

      Any suggesion?

      It seems to do an update only twice?

      int status = tag_device0.Write_Tag(0, writeDat, en_statusDat, pb);

      worker.ReportProgress(pb.Value);

      if (ReadTag)
      {
      worker.ReportProgress(0);
      byte[] tagData = new byte[1024];
      tag5_device0.Read_Tag(0, 0, tagData .Length, ref tagData , pb);
      worker.ReportProgress(pb.Value);
      }

      FWIW; the more often you report progress, the longer it'll take to complete the task.

      Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

      1 Reply Last reply
      0
      • B Blubbo

        I've come across with this progress bar using worker.ReportProgress(). I was hoping to get a real-time progress Bar value from outside Write_Tag method. In this code below, it does seem to have some 1-2 seconds delay before showing the progress bar status. Any suggesion?

        private void InitializeProgressBars()
        {
        for (int i = 0; i < DevicePath.Count; i++)
        {
        progressBar[i] = new ProgressBar();
        progressBar[i].Location = new Point(3, 16);
        progressBar[i].Size = new Size(605, 31);
        progressBar[i].Maximum = 100;
        }

        gbProgressStatus0.Controls.Add(progressBar\[0\]);
        gbProgressStatus1.Controls.Add(progressBar\[1\]);
        gbProgressStatus2.Controls.Add(progressBar\[2\]);
        gbProgressStatus3.Controls.Add(progressBar\[3\]);
        

        }

        private void InitializeBackgroundWorkers()
        {
        for (var f = 0; f < DevicePath.Count; f++)
        {
        bw[f] = new BackgroundWorker();
        bw[f].WorkerReportsProgress = true;
        bw[f].WorkerSupportsCancellation = true;

           switch (f)
           {
              case 0:
              {
                  bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork0);
                  bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted0);
                  break;
              }
              case 1:
              {
                  bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork1);
                  bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted1);
                  break;
              }
              case 2:
              {
                  bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork2);
                  bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted2);
                  break;
               }
               case 3:
               {
                  bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork3);
                  bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted3);
                  break;
               }
            }
         }
        
         bw\[0\].ProgressChanged += (sender, e) => { progressBar\[0\].Value = e.ProgressPercentage; };
         bw\[1\].ProgressChanged += (sender, e) => { progressBar\[1\].Value = e.ProgressPercentage; };
         bw\[2\].ProgressChanged += (sender, e) => { progressBar\[2\].Value = e.ProgressPercentage; };
         bw\[3\].ProgressChanged += (sender, e) => { progressBar\[3\].Value = e.ProgressPercent
        
        M Offline
        M Offline
        Matt T Heffron
        wrote on last edited by
        #3

        (This looks like Windows Forms vs. WPF.) In the ...DoWork_n_() method you create a local ProgressBar that is passed to the Write_Tag and Read_Tag methods. There's not a tight linkage between that ProgressBar and the one that ReportProgress() is updating, so the one that is actually visible is not updated very often. If the Write_Tag and Read_Tag methods aren't careful to deal with possible cross-thread updating of the ProgressBar passed to them, then you're kind of out-of-luck. It doesn't appear that there's an event on the ProgressBar that could be used to redirect the updates to the .Value to use the worker.ReportProgress(..). If the Write_Tag and Read_Tag methods are dealing with the cross-thread updating correctly, then you can pass the visible ProgressBar into the BackgroundWorker with the argument to the RunWorkerAsync(progressBar[_n_]) and use the ReportProgress() when updating directly in the worker, and pass it into the Write_Tag and Read_Tag methods, counting on them to "do the right thing" when they update it. Something like:

        private void InitializeProgressBars()
        {
        for (int i = 0; i < DevicePath.Count; i++)
        {
        progressBar[i] = new ProgressBar();
        progressBar[i].Location = new Point(3, 16);
        progressBar[i].Size = new Size(605, 31);
        progressBar[i].Maximum = 100;
        }

        gbProgressStatus0.Controls.Add(progressBar[0]);
        gbProgressStatus1.Controls.Add(progressBar[1]);
        gbProgressStatus2.Controls.Add(progressBar[2]);
        gbProgressStatus3.Controls.Add(progressBar[3]);
        }

        private void InitializeBackgroundWorkers()
        {
        for (var f = 0; f < DevicePath.Count; f++)
        {
        bw[f] = new BackgroundWorker();
        bw[f].WorkerReportsProgress = true;
        bw[f].WorkerSupportsCancellation = true;

        switch (f)
        {
          case 0:
          {
            bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork0);
            bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted0);
            break;
          }
          case 1:
          {
            bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork1);
            bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted1);
        
        B 1 Reply Last reply
        0
        • M Matt T Heffron

          (This looks like Windows Forms vs. WPF.) In the ...DoWork_n_() method you create a local ProgressBar that is passed to the Write_Tag and Read_Tag methods. There's not a tight linkage between that ProgressBar and the one that ReportProgress() is updating, so the one that is actually visible is not updated very often. If the Write_Tag and Read_Tag methods aren't careful to deal with possible cross-thread updating of the ProgressBar passed to them, then you're kind of out-of-luck. It doesn't appear that there's an event on the ProgressBar that could be used to redirect the updates to the .Value to use the worker.ReportProgress(..). If the Write_Tag and Read_Tag methods are dealing with the cross-thread updating correctly, then you can pass the visible ProgressBar into the BackgroundWorker with the argument to the RunWorkerAsync(progressBar[_n_]) and use the ReportProgress() when updating directly in the worker, and pass it into the Write_Tag and Read_Tag methods, counting on them to "do the right thing" when they update it. Something like:

          private void InitializeProgressBars()
          {
          for (int i = 0; i < DevicePath.Count; i++)
          {
          progressBar[i] = new ProgressBar();
          progressBar[i].Location = new Point(3, 16);
          progressBar[i].Size = new Size(605, 31);
          progressBar[i].Maximum = 100;
          }

          gbProgressStatus0.Controls.Add(progressBar[0]);
          gbProgressStatus1.Controls.Add(progressBar[1]);
          gbProgressStatus2.Controls.Add(progressBar[2]);
          gbProgressStatus3.Controls.Add(progressBar[3]);
          }

          private void InitializeBackgroundWorkers()
          {
          for (var f = 0; f < DevicePath.Count; f++)
          {
          bw[f] = new BackgroundWorker();
          bw[f].WorkerReportsProgress = true;
          bw[f].WorkerSupportsCancellation = true;

          switch (f)
          {
            case 0:
            {
              bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork0);
              bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted0);
              break;
            }
            case 1:
            {
              bw\[f\].DoWork += new DoWorkEventHandler(BackgroundWorkerFilesDoWork1);
              bw\[f\].RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorkerFilesRunWorkerCompleted1);
          
          B Offline
          B Offline
          Blubbo
          wrote on last edited by
          #4

          I have came up with a solution before I saw this reply with Action. I placed a new method in the class (same class with Read_Tag method in it). Works gracefully!

          void UpdateProgressBar(ProgressBar pb, int value)
          {
          if (pb.InvokeRequired)
          {
          Action action = new Action(UpdateProgressBar);
          object[] obj = new object[] { pb, value };
          pb.BeginInvoke(action, obj);
          }
          else
          pb.Value = value;
          }

          public int tag5_device0.Read_Tag(, ProgressBar pb)
          {
          //code snippet

          for (int i = 0; i < 44; i++)
          {
          UpdateProgressBar(pb, i);
          }

          M 1 Reply Last reply
          0
          • B Blubbo

            I have came up with a solution before I saw this reply with Action. I placed a new method in the class (same class with Read_Tag method in it). Works gracefully!

            void UpdateProgressBar(ProgressBar pb, int value)
            {
            if (pb.InvokeRequired)
            {
            Action action = new Action(UpdateProgressBar);
            object[] obj = new object[] { pb, value };
            pb.BeginInvoke(action, obj);
            }
            else
            pb.Value = value;
            }

            public int tag5_device0.Read_Tag(, ProgressBar pb)
            {
            //code snippet

            for (int i = 0; i < 44; i++)
            {
            UpdateProgressBar(pb, i);
            }

            M Offline
            M Offline
            Matt T Heffron
            wrote on last edited by
            #5

            I think you should just create the delegate once as it doesn't change. And the BeginInvoke's second argument is params so it will assemble the object array automatically, so this might be easier to read:

            private static Action<ProgressBar, int> UpdateProgressBarAction = UpdateProgressBar;
            private static void UpdateProgressBar(ProgressBar pb, int value)
            {
              if (pb.InvokeRequired)
              {
                pb.BeginInvoke(UpdateProgressBarAction, pb, value);
              }
              else
                pb.Value = value;
            }
            

            You could even use a lambda to define this self-referentially to avoid the separate UpdateProgressBarAction:

            private static Action<ProgressBar, int> UpdateProgressBar = (ProgressBar pb, int value) => {
              if (pb.InvokeRequired)
              {
                pb.BeginInvoke(UpdateProgressBar, pb, value);
              }
              else
                pb.Value = value;
            };
            
            B 1 Reply Last reply
            0
            • M Matt T Heffron

              I think you should just create the delegate once as it doesn't change. And the BeginInvoke's second argument is params so it will assemble the object array automatically, so this might be easier to read:

              private static Action<ProgressBar, int> UpdateProgressBarAction = UpdateProgressBar;
              private static void UpdateProgressBar(ProgressBar pb, int value)
              {
                if (pb.InvokeRequired)
                {
                  pb.BeginInvoke(UpdateProgressBarAction, pb, value);
                }
                else
                  pb.Value = value;
              }
              

              You could even use a lambda to define this self-referentially to avoid the separate UpdateProgressBarAction:

              private static Action<ProgressBar, int> UpdateProgressBar = (ProgressBar pb, int value) => {
                if (pb.InvokeRequired)
                {
                  pb.BeginInvoke(UpdateProgressBar, pb, value);
                }
                else
                  pb.Value = value;
              };
              
              B Offline
              B Offline
              Blubbo
              wrote on last edited by
              #6

              Thanks for the suggestion. I'm still working on using the delegation of the code. I have never used it in my prior programs that I have created. Still learning new stuff. Thanks again!

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups