Right. You can't make your progress bar truly smooth unless you know
exactly how long the entire operation is going to take.
You can, however, make those long parts of the operation appear to be more
responsive. My solution for this type of problem is to have the class that
encapsulates each step expose a "NumSteps" quantity. Before you start the
operation, you query each step for it's NumSteps, and add them all up. Then
set your ProgressBar.Start to 0, and ProgressBar.End to that total amount.
Now here's the important part. The classes that encapsulate each step each
have to define an event that they can use to report on their own progress.
You can make a single event handler in your main class to handle all of
those events, in which you just increment your ProgressBar.Value. Something
like this:
namespace myApp {
// A delegate for all those "intermediate progress" events:
public delegate void StepProgress(object sender, EventArgs e);
// three classes for three steps:
class A {
public event StepProgress AProgress;
public int NumSteps() { return 5; }
public void DoSomeWork() {
for(int i = 0; i < 5; i++) {
// blah blah blah
if(AProgress != null)
AProgress(this, (EventArgs)null);
}
}
}
class B {
// just like A, except that NumSteps is 12, and
// the DoSomeWork() method will invoke BProgress 12 times
}
class C {
// just like A, except that NumSteps is 2, and
// the DoSomeWork() method will invoke CProgress 2 times
}
class myMainClass {
public void HandleStepProgressEvents(object sender, EventArgs e) {
myProgressBar.Value++;
}
private void DoTheLongOperation() {
// create the worker objects.
A myA = new A();
B myB = new B();
C myC = new C();
// subscribe to their step events
A.AProgress += new StepProgress(HandleStepProgressEvents);
B.BProgress += new StepProgress(HandleStepProgressEvents);
C.CProgress += new StepProgress(HandleStepProgressEvents);
// set up my progress bar.
int TotalSteps = myA.NumSteps() + myB.NumSteps() + myC.NumSteps();
myProgressBar.Start = 0;
myProgressBar.Value = 0;
myProgressBar.End = TotalSteps;
A.DoSomeWork(); // presumably these methods spawn their own
threads
B.DoSomeWork(); // to do the actual work, otherwise you'll freeze
your UI
C.DoSomeWork(); // while the work is taking place.
}
}
}
So in this example, rather than only displaying 3 increments--one for A, one
for B, and one for C--you get 19 steps: 5 for A, 12 for B, and 2 for C.
This is still not perfect, as there's no real way to make sure each little
step is roughly the same amount of time, but at least it's better. And if
you have a step that might take 10 minutes, you can always have that event
report more steps back to the UI. Maybe 100, so you get a progress bar
update every 6 seconds.
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in
message news:ez*************@TK2MSFTNGP15.phx.gbl...
jez123456,
You could, but in order to do that, you would need to have an
estimation of when the step was going to complete. Once you know that,
you can basically divide the time by the number of pixels one step is, and
then every time that amount of time elapses, write one more bar with a
length of 1 pixel to the progress bar.
For example, if you know it will take 10 seconds to complete the
current step, and the current step on the progress bar is five pixels
wide, draw the progress bar which is one pixel wider than the current
every two seconds.
Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com
"jez123456" <je*******@discussions.microsoft.com> wrote in message
news:3E**********************************@microsof t.com... Hi, thanks for the previous advice on progressbars with showing the
percentage. I would now like to create a less clunky version.
I.e at the moment my progressbar shows 7 separate steps. Some steps can
take
seconds to process, but others could take upto 10 minutes (leaving the
users
thinking nothing is happening!).
Is there a way to show the progressbar smoothly increasing until the
final
step has finished instead of clunking it's way across?