GeneK
GeneK

Reputation: 41

C# Progress Bar not cooperating

I've run into a really weird situation. This should be so simple, yet I'm not sure why it's happening.

I have a marquee progress bar set to visible=false as it's initial state. Then at one point during runtime I call one of my functions and right before calling it I set the PB to visible=true and after the function ends, I set it back to visible=false. It doesn't get any simpler then this.

If (something)
{
  pb.visible=true;
  runMyfunction(x, x, x, x,);
  pb.visible=false;
}

The problem is that I never see the PB. If I comment out my function and remove =false, the PB shows up, but as soon as I get my function back in there, PB never shows up.

I've tried various approaches. Using If statements to make sure I get a progress bar before it ever touches the function and it still keeps the PB hidden.

Am I missing something? This does not seem like it should be so complicated. Show object, run function, hide object. Right? :)

Upvotes: 2

Views: 2860

Answers (4)

Olav Haugen
Olav Haugen

Reputation: 1351

My guess is myRunFunction() runs on the UI Thread.

Try running it inside a BackgroundWorker and start the ProgressBar before calling RunWorkerAsync and stop it in the RunWorkerCompleted event.

Edited with code example:

public class SomeClass
{
    private BackgroundWorker _myFunctionBackgroundWorker;
    private SomeProgressBar pb;

    public SomeClass()
    {
        _myFunctionBackgroundWorker = new BackgroundWorker();
        _myFunctionBackgroundWorker.DoWork += myFunctionBackgroundWorker_DoWork;
        _myFunctionBackgroundWorker.RunWorkerCompleted += myFunctionBackgroundWorker_RunWorkerCompleted;

        pb.visible = true;
        _myFunctionBackgroundWorker.RunWorkerAsync();
    }

    private void myFunctionBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        runMyfunction();
    }


    private void myFunctionBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        pb.visible = false;
    }
}

Upvotes: 7

CodingGorilla
CodingGorilla

Reputation: 19842

This is because your function is tieing up the UI thread. Setting the ProgressBar to visible requires the UI thread to be freed up to draw it, but instead you continue to process your function which never gives it time to draw.

You can sort of work around this by calling: Application.DoEvents Which stops processing your method long enough to process some windows messages (and do the related drawing).

The big problem with Application.DoEvents is that assuming you're updating your Progress Bar from your runMyfunction() you're going to have to constantly call Application.DoEvents to allow your PB to draw, or you'll see it, but you'll never see it update.

A better solution is to push your runMyfunction() call to a background thread and update the progress bar asynchronously from there. That, of course is a lot more complicated, but makes for a better user experience.

Upvotes: 7

Tony Abrams
Tony Abrams

Reputation: 4673

It could be that your function is running and completing too fast for you to see the bar. I know that I've had this happen a few times before.

Upvotes: 1

Mike Marshall
Mike Marshall

Reputation: 7850

inside of your runMyFunction() method call Application.DoEvents() to force your app to redraw and process the windows message loop:

e.g.

void myRunFunction()
{
  while (someFlag)
  {
   // do work
   pb.Value = someValue;
   Application.DoEvents();
  }
}

Upvotes: 2

Related Questions