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
Related
I am wondering what is the best way to achieve this in Windows Forms - what I need is a window showing time elapsed (1 sec 2 secs etc) up to 90 seconds while code is being executed. I have a timer right now implemented as follows but I think I also need a stopwatch there as well since the Timer blocks the main thread.
static System.Timers.Timer pXRFTimer = new System.Timers.Timer();
static int _pXRFTimerCounter = 0;
private void ScanpXRF()
{
_pXRFTimerCounter = 0;
pXRFTimer.Enabled = true;
pXRFTimer.Interval = 1000;
pXRFTimer.Elapsed += new ElapsedEventHandler(pXRFTimer_Tick);
pXRFTimer.Start();
//START action to be measured here!
DoSomethingToBeMeasured();
}
private static void pXRFTimer_Tick(Object sender, EventArgs e)
{
_pXRFTimerCounter++;
if (_pXRFTimerCounter >= 90)
{
pXRFTimer.Stop();
}
else
{
//show time elapsed
}
}
I'm not sure about mechanics of your app, but time elapsed can be calculated with something like this
DateTime startUtc;
private void ScanpXRF()
{
startUtc = DateTime.NowUtc;
(...)
//START action to be measured here!
}
private static void pXRFTimer_Tick(Object sender, EventArgs e)
{
var elapsed = DateTime.NowUtc - startUtc;
var elapsedSeconds = elapsed.TotalSeconds; // double so you may want to round.
}
I have a method which does some calculations.
public void CalculateItems()
{
// Calculate the empty Items
}
Which I need to execute in every 30th second of a minute.
If my service starts at 10:00:15, The method should start working from 10:00:30, 10:01:00, 10:01:30 and goes on.
If my Service starts at 10:00:50, The method should start working from 10:01:00, 10:01:30, 10:02:00 and goes on.
I have tried System.Threading.Timer, System.Timers.Timer but in all these, I couldn't achieve my scenario. Please help with your valuable suggestions.
What I have tried is in System.Threading.Timer
var timer = new System.Threading.Timer(
e => CalculateItems(),
null,
TimeSpan.Zero,
TimeSpan.FromSeconds(30));
But it hits my method every 30th second Not in 30th second of every minute
One simple way to solve it using a timer is to set the interval to a single second, and in the timer's callback method to check if the value of DateTime.Now.Seconds divides by 30:
void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(DateTime.Now.Seconds % 30 == 0)
{
CalculateItems();
}
}
You can initially start the timer with 1 second interval. Then in the Timer Event, if DateTime.Now.Second is 30 or 0, You can set the interval to 30 seconds. From then on your event would be triggered only at specified time.
System.Timers.Timer timer= new System.Timers.Timer(1000);
private void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
{
if(timer.Interval!=30000 && DateTime.Now.Seconds % 30 == 0)
{
timer.Stop();
timer.Interval = 30000;
timer.Start();
DoWork();
}
else
{
if(timer.Interval==30000)
{
DoWork();
}
}
}
I solved it with timers, and calculating the sime to the next 30 sec block:
It is recalculating the 30 sec again after elapsed, otherwise it will slightly get a delta after each run.
class Program
{
static System.Threading.Timer _ttimer;
static void Main(string[] args)
{
SetupTimerTo30sec();
Console.ReadLine();
}
private static void SetupTimerTo30sec()
{
var now = DateTime.Now;
int diffMilliseconds;
if (now.Second < 30)
{
diffMilliseconds = (30 - now.Second) * 1000;
}
else
{
diffMilliseconds = (60 - now.Second) * 1000;
}
diffMilliseconds -= now.Millisecond;
if (_ttimer != null)
{
_ttimer.Change(diffMilliseconds, 30 * 1000);
}
else
{
_ttimer = new Timer(OnElapsed, null, diffMilliseconds, 30 * 1000);
}
}
private static void OnElapsed(object state)
{
Console.Write(DateTime.Now.ToLongTimeString());
Console.WriteLine($":{DateTime.Now.Millisecond}");
SetupTimerTo30sec();
}
}
I have numericUpDown1 that when I set its value it's saving the value in options text file:
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
Options_DB.Set_Radar_Images_Time(numericUpDown1.Value);
}
timer1 interval set to 1000ms in the form1 designer.
In timer1 tick event I have:
private void timer1_Tick(object sender, EventArgs e)
{
numbers_radar = Convert.ToInt64(numericUpDown1.Value);
}
Now I want to assign the timer tick event to: label21.Text and display the minutes counting down.
If I set the numericUpDown1 to 10 so it will count down 10 minutes.
The format should be like: minutes:seconds (00:00).
And each time the timer get to 1 it should call this method: fileDownloadRadar();
Each time when it's get to 1 the timer should be reset to the numericUpDown1 value and start over again counting back and each time in the end to call the method fileDownloadRadar();
The numericUpDown1 is set to minimum 5 and maximum 60
EDIT
Now i tried this code but i don't see anything change on label21 when starting the timer.
And minutes is starting as 0 but should be in this case 29(value of numericUpDown1).
And should i check if minutes and seconds == 1 or == 0 ? What's more logic 1 or 0 ?
private void timer1_Tick(object sender, EventArgs e)
{
numOfMinutes = Convert.ToInt32(numericUpDown1.Value);
int seconds = numOfMinutes % 60;
int minutes = numOfMinutes / 60;
seconds --;
string time = minutes + ":" + seconds;
label21.Text = time;
if (seconds == 1)
{
minutes --;
}
if (minutes == 1 && seconds == 1)
{
numOfMinutes = Convert.ToInt32(numericUpDown1.Value);
fileDownloadRadar();
}
}
I think you could better use a TimeSpan object and start as follows.
declare a TimeSpan variable in your object (thus a private field):
private TimeSpan span;
Just below the code where you start the timer, initialize the span variable:
timer1.Start(); // this should exist somewhere
TimeSpan span = new TimeSpan(0, numericUpDown1.Value, 0);
In your timer event handler, write this code:
private void timer1_Tick(object sender, EventArgs e)
{
span = span.Subtract(new TimeSpan(0, 0, 1));
label21.Text = span.ToString(#"mm\:ss");
if (span.TotalSeconds < 1)
{
span = new TimeSpan(0, numericUpDown1.Value, 0);
fileDownloadRadar();
}
}
I'm not sure what you want in the if statement, but I hope this will help you further.
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.
I am using a timer in my code. Status bar updates in tick event on clicking respective button for the time inteval mentioned in properties say one second. Now i want to use the same timer for a different time interval say two seconds for a different oepration. How to achieve that?
Create a second timer. There is nothing to gain from hacking the first timer.
As #Henk noted, Timers are not that expensive. (Especially not compared to fixing hard to maintain code!)
I agree with #Henk and others.
But still, something like this could work:
Example
Int32 counter = 0;
private void timer1_Tick(object sender, EventArgs e)
{
if (counter % 1 == 0)
{
OnOneSecond();
}
if (counter % 2 == 0)
{
OnTwoSecond();
})
counter++;
}
Updated Example
private void Form_Load()
{
timer1.Interval = 1000; // 1 second
timer1.Start(); // This will raise Tick event after 1 second
OnTick(); // So, call Tick event explicitly when we start timer
}
Int32 counter = 0;
private void timer1_Tick(object sender, EventArgs e)
{
OnTick();
}
private void OnTick()
{
if (counter % 1 == 0)
{
OnOneSecond();
}
if (counter % 2 == 0)
{
OnTwoSecond();
}
counter++;
}
Change timer Interval property.
Change the Interval property in every elapsed time. for example, this program process data 30 seconds and sleep 10 seconds.
static class Program
{
private System.Timers.Timer _sleepTimer;
private bool _isSleeping = false;
private int _processTime;
private int _noProcessTime;
static void Main()
{
_processTime = 30000; //30 seconds
_noProcessTime = 10000; //10 seconds
this._sleepTimer = new System.Timers.Timer();
this._sleepTimer.Interval = _processTime;
this._sleepTimer.Elapsed += new System.Timers.ElapsedEventHandler(sleepTimer_Elapsed);
ProcessTimer();
this._sleepTimer.Start();
}
private void sleepTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
ProcessTimer();
}
private void ProcessTimer()
{
_sleepTimer.Enabled = false;
_isSleeping = !_isSleeping;
if (_isSleeping)
{
_sleepTimer.Interval = _processTime;
//process data HERE on new thread;
}
else
{
_sleepTimer.Interval = _noProcessTime;
//wait fired thread and sleep
Task.WaitAll(this.Tasks.ToArray());
}
_sleepTimer.Enabled = true;
}
}