ProgressBar runs too fast than defined - c#

my application runs files and every file has it's own running time.
this function get in millisecond the time that the progress time should run:
timerProgress = my timer
pbStatus = my progress bar
public void AnimateProgBar(int milliSeconds)
{
if (!timerProgress.Enabled && milliSeconds != 0)
{
pbStatus.Value = 0;;
timerProgress.Interval = milliSeconds / 100;
timerProgress.Enabled = true;
}
}
and this is my timer that fill the progress bar:
private void timerProgress_Tick(object sender, EventArgs e)
{
if (pbStatus.Value < 100)
{
pbStatus.Value += 1;
pbStatus.Refresh();
}
else
{
timerProgress.Enabled = false;
}
}
my problem is that progress bar runs too fast for example if AnimateProgBar get the value of 12000 (12 seconds) the progress bar runs only for 6-7 seconds.

It's fishy that your code doesn't work. I tried it a few times, and it missed with about 0.6 seconds each time; it seems like the timer is just imprecise.
What you could do is to take care of the time yourself instead of trusting a timer:
WithEvents Tmr As New Timer With {.Interval = 100}
Dim startTime As Date, AnimationTime%
Sub AnimateProgress(ms%)
If ms <= 0 Then Exit Sub
ProgressBar1.Value = 0
AnimationTime = ms
startTime = Now
Tmr.Start()
End Sub
Private Sub Tmr_Tick() Handles Tmr.Tick
ProgressBar1.Value = Math.Min((Now - startTime).TotalMilliseconds / AnimationTime, 1) * 100
If ProgressBar1.Value = 100 Then Tmr.Stop()
End Sub
EDIT - Response to the reply bellow:
Oh sorry, no it's vb.net. I know both the languages just as well, but I prefer vb, and tend to think that everypony else does so too.
Here's the c# version:
DateTime startTime; int animationTime;
void AnimateProgress(int ms) {
if (ms <= 0) return;
progressBar1.Value = 0;
animationTime = ms;
startTime = DateTime.Now;
Tmr.Start();
}
private void Tmr_Tick(object sender, EventArgs e) {
progressBar1.Value = (int)(Math.Min((DateTime.Now - startTime).TotalMilliseconds / animationTime, 1) * 100);
if (progressBar1.Value == 100) Tmr.Stop();
}

You can try with this sample, based on PerformStep method
var progressBar = new System.Windows.Forms.ProgressBar();
progressBar.Maximum = 100;
progressBar.Minimum = 0;
progressBar.Step = 10;
//begin loop
//Your treatment of step
progressBar.PerformStep();
//end loop
msdn link : http://msdn.microsoft.com/fr-fr/library/system.windows.forms.progressbar.performstep(v=vs.80).aspx
You have sample here
private void CopyWithProgress(string[] filenames)
{
// Display the ProgressBar control.
pBar1.Visible = true;
// Set Minimum to 1 to represent the first file being copied.
pBar1.Minimum = 1;
// Set Maximum to the total number of files to copy.
pBar1.Maximum = filenames.Length;
// Set the initial value of the ProgressBar.
pBar1.Value = 1;
// Set the Step property to a value of 1 to represent each file being copied.
pBar1.Step = 1;
// Loop through all files to copy.
for (int x = 1; x <= filenames.Length; x++)
{
// Copy the file and increment the ProgressBar if successful.
if(CopyFile(filenames[x-1]) == true)
{
// Perform the increment on the ProgressBar.
pBar1.PerformStep();
}
}
}
link : http://msdn.microsoft.com/fr-fr/library/system.windows.forms.progressbar.performstep(v=vs.80).aspx

I couldn't reproduce your issue. I just tested a new form, with a ProgressBar and a Timer as you detailed in your question, and merely added one button to start the test, and one label to show the elapsed time:
DateTime start;
private void button1_Click(object sender, EventArgs e)
{
start = DateTime.Now;
AnimateProgBar(12000);
}
private void timer1_Tick(object sender, EventArgs e)
{
label1.Text = DateTime.Now.Subtract(start).TotalSeconds.ToString();
//the rest of your code, starting with "if (pbStatus.Value < 100)"
I consistently got 12.6 seconds until the progressBar filled (and the timer stopped, freezing the label text)... Maybe part of your progressBar is hidden?
[Edit]
If you're curious about the 0.6 extra seconds that BlackCap also noticed, it's because you're setting the timer interval to 120 milliseconds, but timer events have a resolution of about 18 milliseconds, so it will actually fire at 126 instead of 120.

Related

Why is the event RunWorkerCompletedEventArgs launched before I finished loading the progress bar in its entirety?

When I'm running a heavy task or a few data, at the end of the task the label showing the percentage reaches 100% correctly and displays the finalized message, but even the progressBar has not loaded in its entirety, when the completion message is displayed you can see the animation of the progress bar that completes your work.
I have not been able to solve this problem, and the natural way that a progress bar should work as in all the systems that I have seen, the progress is completed and then show a finished message.
Here I leave an example:
BackgroundWorker bg = new BackgroundWorker();
private void btnRun_Click(object sender, EventArgs e)
{
bg.WorkerReportsProgress = true;
bg.ProgressChanged += bg_ProgressChanged;
bg.DoWork += bg_DoWork;
bg.RunWorkerCompleted += bg_RunWorkerCompleted;
bg.RunWorkerAsync();
label1.Visible = true;
progressBar1.Visible = true;
}
Dowork Event:
private void bg_DoWork(object sender, DoWorkEventArgs e)
{
int progress = 0, percent = 0;
for (int i = 0; i < ds.Tables[0].Rows.Count; i++) //Cycle that will represent the heavy task
{
totalRecords = ds.Tables[0].Rows.Count;
progress++;
percent = Convert.ToInt16((((double)progress / (double)totalRecords ) * 100.00));
System.Threading.Thread.Sleep(500);
bg.ReportProgress(percent );
}
}
ProgressChanged
private void bg_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Change the value of the ProgressBar to the BackgroundWorker progress.
progressBar1.Step = 1;
progressBar1.Style = ProgressBarStyle.Continuous;
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
if (e.ProgressPercentage > 100)
{
label1.Text = "100%";
progressBar1.Value = progressBar1.Maximum;
}
else
{
label1.Text = Convert.ToString(e.ProgressPercentage) + "%";
progressBar1.Value = e.ProgressPercentage;
}
}
Finally, the RunWorkerCompleted event that is executed when the BackgroundWorker has finished:
private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done...");
label1.Visible = false;
progressBar1.Visible = false;
}
How can I solve this progress bar animation problem?
Environment: Visual Studio 2010 (WindowsForms) & .NET NetFramework 4.
I think you're facing a classic problem of Windows' Aero animations.
Informations extracted from this page.
This lag happens when a progress bar is incremented. But it doesn't happen when the progress bar is decremented.
So basically, what you want to do is move past the actual value you should get to, then decrement to the actual value.
The author of the page uses an extension method, feel free to do as well; I'm just putting the relevant code here:
// To get around the progressive animation, we need to move the
// progress bar backwards.
if (value == pb.Maximum)
{
// Special case as value can't be set greater than Maximum.
pb.Maximum = value + 1; // Temporarily increase Maximum
pb.Value = value + 1; // Move past
pb.Maximum = value; // Reset maximum
}
else
{
pb.Value = value + 1; // Move past
}
pb.Value = value;

C# timer stop after some number of ticks automatically

How to stop a timer after some numbers of ticks or after, let's say, 3-4 seconds?
So I start a timer and I want after 10 ticks or after 2-3 seconds to stop automatically.
Thanks!
You can keep a counter like
int counter = 0;
then in every tick you increment it. After your limit you can stop timer then. Do this in your tick event
counter++;
if(counter ==10) //or whatever your limit is
yourtimer.Stop();
When the timer's specified interval is reached (after 3 seconds), timer1_Tick() event handler will be called and you could stop the timer within the event handler.
Timer timer1 = new Timer();
timer1.Interval = 3000;
timer1.Enabled = true;
timer1.Tick += new System.EventHandler(timer1_Tick);
void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop(); // or timer1.Enabled = false;
}
i generally talking because you didn't mention which timer, but they all have ticks... so:
you'll need a counter in the class like
int count;
which you'll initialize in the start of your timer, and you'll need a dateTime like
DateTime start;
which you'll initialize in the start of your timer:
start = DateTime.Now;
and in your tick method you'll do:
if(count++ == 10 || (DateTime.Now - start).TotalSeconds > 2)
timer.stop()
here is a full example
public partial class meClass : Form
{
private System.Windows.Forms.Timer t;
private int count;
private DateTime start;
public meClass()
{
t = new Timer();
t.Interval = 50;
t.Tick += new EventHandler(t_Tick);
count = 0;
start = DateTime.Now;
t.Start();
}
void t_Tick(object sender, EventArgs e)
{
if (count++ >= 10 || (DateTime.Now - start).TotalSeconds > 10)
{
t.Stop();
}
// do your stuff
}
}
Assuming you are using the System.Windows.Forms.Tick. You can keep track of a counter, and the time it lives like so. Its a nice way to use the Tag property of a timer.
This makes it reusable for other timers and keeps your code generic, instead of using a globally defined int counter for each timer.
this code is quiet generic as you can assign this event handler to manage the time it lives, and another event handler to handle the specific actions the timer was created for.
System.Windows.Forms.Timer ExampleTimer = new System.Windows.Forms.Timer();
ExampleTimer.Tag = new CustomTimerStruct
{
Counter = 0,
StartDateTime = DateTime.Now,
MaximumSecondsToLive = 10,
MaximumTicksToLive = 4
};
//Note the order of assigning the handlers. As this is the order they are executed.
ExampleTimer.Tick += Generic_Tick;
ExampleTimer.Tick += Work_Tick;
ExampleTimer.Interval = 1;
ExampleTimer.Start();
public struct CustomTimerStruct
{
public uint Counter;
public DateTime StartDateTime;
public uint MaximumSecondsToLive;
public uint MaximumTicksToLive;
}
void Generic_Tick(object sender, EventArgs e)
{
System.Windows.Forms.Timer thisTimer = sender as System.Windows.Forms.Timer;
CustomTimerStruct TimerInfo = (CustomTimerStruct)thisTimer.Tag;
TimerInfo.Counter++;
//Stop the timer based on its number of ticks
if (TimerInfo.Counter > TimerInfo.MaximumTicksToLive) thisTimer.Stop();
//Stops the timer based on the time its alive
if (DateTime.Now.Subtract(TimerInfo.StartDateTime).TotalSeconds > TimerInfo.MaximumSecondsToLive) thisTimer.Stop();
}
void Work_Tick(object sender, EventArgs e)
{
//Do work specifically for this timer
}
When initializing your timer set a tag value to 0 (zero).
tmrAutoStop.Tag = 0;
Then, with every tick add one...
tmrAutoStop.Tag = int.Parse(tmrAutoStop.Tag.ToString()) + 1;
and check if it reached your desired number:
if (int.Parse(tmrAutoStop.Tag.ToString()) >= 10)
{
//do timer cleanup
}
Use this same technique to alternate the timer associated event:
if (int.Parse(tmrAutoStop.Tag.ToString()) % 2 == 0)
{
//do something...
}
else
{
//do something else...
}
To check elapsed time (in seconds):
int m = int.Parse(tmrAutoStop.Tag.ToString()) * (1000 / tmrAutoStop.Interval);

Display a timer that loops every 15 seconds

I made this code, but there is a delay between the time loop showing on the screen and the exact elapsed time.
Timer t = new Timer();
int time = 15;
string timestr;
t.Interval = 1000;
t.Tick += new EventHandler(Time);
void Time(object sender, EventArgs e)
{
if (time == 0)
{ time = 15; }
if (time != 0)
{
time--;
timestr = time.ToString();
label.Text = timestr;
}
}
My guess is that you are off by one second since the timer won't fire its first event until that interval value is reached.
A quick fix would be to fire the event yourself when you start it:
t.Start();
Time(t, EventArgs.Empty);
I think you need to try this. Add the line Application.DoEvents() just before the end of Time function.
void Time(object sender, EventArgs e)
{
if (time == 0)
{ time = 15; }
if (time != 0)
{
time--;
timestr = time.ToString();
label.Text = timestr;
}
Application.DoEvents();
}

Save remaining seconds in countdown timer

I have a problem. I want to save the remaining seconds in countdown timer (for example, the remaining time = 12 seconds) i want to save that 12 seconds in a variable.
this is my code
int order = 0;
bool right = true;
DispatcherTimer timer1 = new DispatcherTimer();
private void timer_start()
{
timer1.Interval = new TimeSpan(0, 0, 0, 1);
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Start();
}
int remainingSecond;
int tik = 15;
void timer1_Tick(object sender, EventArgs e)
{
this.Timer.Text = tik.ToString();
if (tik > 0)
{
tik--;
if (this.order >= 5)
{
timer1.Stop();
if (right)
{
remainingSecond = tik;
}
else
remainingSecond = 0;
}
}
else
{
remainingSecond = 0;
timer1.Stop();
}
}
everytime I write "remainingSecond" , its value is always 0. I wish that remainingSecond value is 12. Help me, please. Thanks
You assigned order = 0 but did not increase it any where and set this condition
if (this.order >= 5) which will never true. So it will keep decrementing your tik and at the end your this condition if (tik > 0) will become false. So else will be executed and it will set your remainingSecond to ZERO. Thats why you are getting ZERO as output.
Your timer is ticking in every 1milisecond. The timer will start, and it will tick immediately, at that time order will be zero, and your else statement will get executed that will set remainingSeconds to ZERo and will Stop the timer as well. So the clicking on the buttons won't do anything for you.
Try to set the interval for 1 second instead of 1 millisecond

Progress Bar run less time than defined - continue previous post

this is my post earlier: Progress Bar run less time than defined
all the answers was that i don't need to divide the milliseconds by 100 and when i try this solution the progress bar run to slow unlike the first time that it runs to fast but i think i need to divide the milliseconds by 100 in order to set each 1% from the total 100% that the progress should run.
for example if i want my progress bar will run for 10 seconds so i i divide 10000 / 10 each 1% (or timer tick) will need to be 100 milliseconds so even if i configure it to 100 it still to fast
void bittwist_progBarEventHandler(object sender, EventArgs e)
{
this.Invoke((MethodInvoker)delegate { AnimateProgBar((int)sender); });
}
public void AnimateProgBar(int milliSeconds)
{
if (!timerProgress.Enabled)
{
this.Invoke((MethodInvoker)delegate { pbStatus.Value = 0; });
timerProgress.Interval = milliSeconds / 100;
timerProgress.Enabled = true;
}
}
private void timerProgress_Tick(object sender, EventArgs e)
{
if (pbStatus.Value < 100)
{
pbStatus.Value += 1;
pbStatus.Refresh();
}
else
{
timerProgress.Enabled = false;
}
}
for example for milliSeconds == 10000 the progress bar runs only for 7 seconds

Categories

Resources