简体   繁体   中英

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? :)

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.

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;
    }
}

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

eg

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM