0

Im trying to update a progress bar while doing some data type checks on a separate thread and there seems to be a delay between what value the progress bar is at and the value which is actually show.

The following code is executed by the non-GUI thread and is used to raise the event.

    protected virtual void OnUpdateProgressBar(object sender, ProgressBarEventArgs e)
    {
        EventHandler<ProgressBarEventArgs> TempHandler = UpdateProgressBar;

        //Avoid possible race condition.
        if (TempHandler != null)
        {
            TempHandler(this, e);
        }
    }

I have created a separate class for updating the progress bar and when i create an instance of it, i pass a reference to the progress bar. Below is the entire class.

public class ProgressBarChanged
{
    ProgressBar statusBar;

    public ProgressBarChanged(ProgressBar pb)
    {
        statusBar = pb;
        statusBar.Value = 0;
    }
    public ProgressBarChanged()
    {
    }

    public void subscribeToEvent(DataVerification test)
    {
        test.UpdateProgressBar += new EventHandler<ProgressBarEventArgs>(incrementPB);
    }

    public void incrementPB(object sender, ProgressBarEventArgs e)
    {
        Action action = () =>
        {
            if (e.CurrentRow == e.FinalRow - 10)
            {
                int i = 5;
            }
            statusBar.Maximum = e.FinalRow;
            statusBar.Value = e.CurrentRow;
        };

        if(statusBar.InvokeRequired)
           statusBar.Invoke(action);
        else
            action();
    }
}

I have uploaded a screen shot showing the progress bar and the actual values. Any ideas???

Thanks

enter image description here

ken2k
  • 48,145
  • 10
  • 116
  • 176
Hans Rudel
  • 3,433
  • 5
  • 39
  • 62
  • Have you tried with `statusBar.Invoke(incrementPB, sender, e);` ? – Steve Mar 09 '12 at 16:21
  • Tried both statusBar.Invoke(incrementPB,sender,e); and statusBar.Invoke(incrementPB(sender,e)); neither work. – Hans Rudel Mar 09 '12 at 16:24
  • @Ken2K, thanks for sorting out the picture. – Hans Rudel Mar 09 '12 at 16:27
  • Perhaps if you could remove the updating of the maximum value, the internal processing of statusbar will be faster. I mean, if you change the maximum at every event, what is the impact on the recalculation of the progress? – Steve Mar 09 '12 at 16:31
  • @Steve: Fair point, ill see about only updating it once as well. Thanks for your help. – Hans Rudel Mar 09 '12 at 16:33

2 Answers2

2

The progessbar is a simple feedback to the user, not a piece of exact instrumentation. It's a pacifier.

It also incorporates it's own async logic to update the screen (independent of the message loop). This makes that it may run a little behind.

What's the big deal?

To get more accurate results, divide your range into < 100 segments and do fewer updates.

H H
  • 263,252
  • 30
  • 330
  • 514
  • @At present the event is getting raised after each row is processed = 130,000 times. ill try, As you have suggested, and raises it less than 100 times and see if that solves the issue. Thanks for your help – Hans Rudel Mar 09 '12 at 16:31
  • 2
    @HansRudel If the Value is updated only 100 times (not 130k times), it'll also reduce CPU consumption a lot, so it's a good idea. – ken2k Mar 09 '12 at 16:39
0

A delay is pretty normal. After all, invoking a method in the UI thread means Windows will dispatch a message and if your thread is fast enough (and CPU consuming) then it'll appear faster than UI.

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • :Thanks for replying. According to Mr Skeet's post here http://stackoverflow.com/questions/229554/whats-the-difference-between-invoke-and-begininvoke i though that the thread would wait for the GUI to process the progress bar update. Or does it change the internal value and then take time to actually show the update? If so is there a way around this delay? – Hans Rudel Mar 09 '12 at 16:26
  • The thread will wait for the PB to _accept the new value_. The visual updating happens separately. – H H Mar 09 '12 at 16:29
  • Try to call Refresh after each value change (but it's not very optimal to have progbar refreshed this way). – ebutusov Mar 09 '12 at 16:35
  • Even if he calls Refresh() from inside the Action that won't change and it can't be called from another thread... – Adriano Repetti Mar 09 '12 at 16:36
  • @Adriano - It certainly could be invoked. – Security Hound Mar 09 '12 at 17:03
  • @ebutusov - calling Refresh 130.000 times would certainly slow things down. A lot. – H H Mar 09 '12 at 18:58
  • @HenkHolterman I know, just wanted to point out that if forced Refresh works as expected, he could call it i.e. every 100th value update. – ebutusov Mar 09 '12 at 19:09
  • @Ramhound even if it __could__ be invoked it's not thread-safe, the only method to refresh a control from another thread is Invalidate(). – Adriano Repetti Mar 12 '12 at 09:37