Reputation: 41
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
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
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
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
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