getting program uptime - c#

I'm beginner to programming. This is my code:
private void timer1_Tick(object sender, EventArgs e)
{
sec++;
textBoxSeconds.Text = sec.ToString();
if (sec > 59)
{
sec = 0;
textBoxSeconds.Text = sec.ToString();
min++;
textBoxMinutes.Text = min.ToString();
}
}
time goes too fast;/ and it stops for few sec sometimes. Hope someone can help me:)
*EDIT//*
thanks for help:) it works, but i still have a problem i didnt menton earlier. time stops sometimes for 1-2 sec, idk why. maybe because of some loops?

This is the wrong approach. When you program starts just save a DateTime instance, i.e. startTime. In your timer tick handler calculate the difference between the current time and the start time and display that.
private DateTime startTime = DateTime.Now;
private void timer1_Tick(object sender, EventArgs e)
{
var delta = DateTime.Now - startTime;
textBoxSeconds.Text = delta.Seconds.ToString("n0");
textBoxMinutes.Text = Math.Floor(delta.TotalMinutes).ToString("n0");
}

Using your code, I can say probably you haven't set the timer Interval, so:
timer1.Interval = 1000; //1000 ms = 1 second
Then you can improve something in the Tick event:
private void timer1_Tick(object sender, EventArgs e)
{
sec++;
if (sec == 60)
{
sec = 0;
min++;
}
textBoxSeconds.Text = sec.ToString();
textBoxMinutes.Text = min.ToString();
}
So use the DateTime class, it's the best solution.
EDIT:
DateTime startTime = DateTime.Now;
void timer1_Tick(object sender, EventArgs e)
{
TimeSpan time = DateTime.Now - startTime;
textBoxSeconds.Text = string.Format("{0:0#}", time.Seconds);
textBoxMinutes.Text = string.Format("{0:0#}", time.Minutes);
}

I agree about startTime - it is mandatory. I've also commented about DataTime.UtcNow - this is correct way.
About your second problem with 1..2 seconds lag - this is because timer's ticks racing side by side with seconds ticks.
1) If your timer will be triggered in 998ms instead of 1000ms, you can read the same amount of second and this number will stay before next tick.
2) Because application is not in real-time priority from OS point of view, it can be held for several seconds (e.g. for rendering multimedia stuff by other app) and you can notice a skip of 1 second...
To solve 1st reason and facilitate 2nd try to increase ticks count by decreasing Interval to 500 or 333.
For more advanced strategy that preserves your resources, you should still use 1000ms but synchronize you timer periodically with each half second crossing using dateTime.Milliseconds. That will maximize probability of avoiding side-by-side racing problem without extra ticks.

Related

Executing an activity at a particular interval

My C# application has to execute a task every few seconds. It is very important that the execution happens at exactly this interval; give or take a few milliseconds.
I tried using a Timer but the time gradually shifts after a few minutes.
The code used by me is as follows:
System.Timers.Timer timerObj = new System.Timers.Timer(10 * 1000);
timerObj.Elapsed += timerObj_Elapsed;
timerObj.AutoReset = true;
timerObj.Start();
static void timerObj_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
DateTime currentTime = DateTime.Now;
Console.WriteLine(currentTime.ToString("HH:mm:ss.fff"));
}
Is there a better way to do this kind of activity?
If it's really important to be that precise, set your timer's interval to something smaller than the max number of milliseconds by which you can be off. (Hopefully this will be greater than 15ms, as that's the resolution of System.Timers.Timer.) Then, in the tick handler, check whether the appropriate amount of time has passed and, if so, call the "real" handler. If your goal is to avoid drift, your test of whether it's time to fire should be based on the time elapsed since starting the timer, not the time elapsed since the last "tick."
You could try to always schedule a singelshot timer via AutoReset = false and calculate the delta on which the timer should fire. This should compensate your skew as it calculates the delta from the absolute time. Here a rough example:
// member variables
DateTime firstSchedule = DateTime.UtcNow;
var numElapsed = 1;
constructor()
{
this.timerObj = new System.Timers.Timer();
timerObj.Interval = CalcDelta();
timerObj.Elapsed += timerObj_Elapsed;
timerObj.AutoReset = false;
timerObj.Start();
}
void timerObj_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.numElapses++;
this.timerObj.Interval = CalcDelta();
this.timerObj.Start();
DateTime currentTime = DateTime.Now;
Console.WriteLine(currentTime.ToString("HH:mm:ss.fff"));
}
private long CalcDelta()
{
DateTime nextSchedule = firstSchedule + TimeSpan.FromSeconds(numElapses * 10);
return (nextSchedule - DateTime.UtcNow).TotalMilliseconds;
}
private void setTimerRepeat(object sender, DoWorkEventArgs e){
DateTime begin = DateTime.Now;
bool isRunning = true;
int sleep=500;
while(isRunning){
int milliSeconds = DateTime.Now.Subtract(begin).TotalMilliSeconds;
if(milliSeconds > 9000){
sleep=10;
}else{
sleep=500;
}
if(milliSeconds=>10000){//if you get drift here, it should be consistent - adjust firing time downward to offset drift (change sleep to a multiple such that sleep%yourNumber==0)
begin = DateTime.Now;
Task.Run(()=>fireEvent());
}
Thread.Sleep(sleep);
}
}
}

C# Time span to string issue

Hello people of stackoverflow.I am having an issue when i try to take a time-span and convert it to a string.
Here is the code:
private void timer1_Tick(object sender, EventArgs e)
{
timeLeft = timeLeft - 1;
TimeLabel.Text = TimeSpan.FromMilliseconds(timeLeft).ToString("h'h 'm'm 's's'");
}
Note that timeLeft is in milliseconds.
However whenever i try to pass this i get 2 sets of minutes sections.
Like this:
Although it should be this amount of time :
I see you´re updating the label every timer ticks and although it´s not shown in the code it looks like your timer interval its set to 1 second probably, Am I right?.
The first thing you´re doing bad is trusting the 1 second interval you set up previously in your timer and hard-coding your code to that interval. The fact is you can´t rely in the timer interval to be precise because most of the timers have a awful resolution time of approximately 14 - 16 ms therefore that´s not a precise way to measure time.
You should use instead the time System.Diagnostics.Stopwatch class which uses the Win32 APIs QueryPerformanceFrequency and QueryPerformanceCounter. Those are the more reliable ways and fast ways to measure time due to the fact that Windows isn´t a Real Time Operation System.
As for how the code will look using I let a sample which should be pretty easy to adapt for you. Besides I include a solution for your TimeSpan - String translation trouble.
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
Console.WriteLine("Starting..");
sw.Start();
Console.ReadLine();
sw.Stop();
Console.WriteLine("Elapsed time {0}:{1}:{2}:{3}", sw.Elapsed.Hours.ToString("00"), sw.Elapsed.Minutes.ToString("00"), sw.Elapsed.Seconds.ToString("00"), sw.Elapsed.Milliseconds);
}
}
Be careful while using the System.Diagnostics.Stopwatch properties, there is a big difference in using the Elapsed.Ticks property and the ElapsedTicks property which it´s explained here.
Hope it helps!!
Due to the fact that there won't be any guarantee that the timer will be fired exactly every millisecond, you have to save a start time and then calculate the elapsed time by subtracting the start time from the current time.
Here is a code snippet to illustrate it:
private DateTime _StartTime;
private void OnCheckBoxTimerEnabledCheckedChanged(object sender, EventArgs e)
{
_StartTime = DateTime.UtcNow;
timer.Enabled = checkBoxTimerEnabled.Checked;
}
private void OnTimerTick(object sender, System.EventArgs e)
{
var now = DateTime.UtcNow;
labelTimeElapsed.Text = (now - _StartTime).ToString("h'h 'm'm 's's'");
}
In that case you also don't need to fire the timer every millisecond. Just fire it every 100ms to be accurate enough for the users eye.
And another tip:
If you need to calculate relative times on your own you should always stick to DateTime.UtcNow and NOT DateTime.Now. So you won't get into trouble when your timer is running when you switch from normal time to summer time or vice versa.
there is nothing wrong with your code. but i guess you Think there is since the above sample shows
2:02:56 and the other 02:03:00 wich is rather Close missing some 3200 milliseconds...
what is the actual value of timeLeft?
Read some more in the documentation on customizing timespan strings
Using a Timer's Tick event to track passing time will result in inaccuracies as Lasse V. Karlsen mentioned in their comment on your question.
What you want to do is store a timestamp (DateTime.Now) when the timer begins, and compare that with a new DateTime.Now each time the timer ticks, like so:
DateTime timestamp;
TimeSpan timeLeft;
private void begin_timer()
{
timestamp = DateTime.Now;
timer1.start();
}
private void timer1_Tick(object sender, EventArgs e)
{
timeLeft = DateTime.Now - timestamp;
TimeLabel.Text = timeLeft.ToString("HH:mm:ss.fff");
}

How do I check how much time remains before timer fires next event?

For example, I have set timer1.Interval to 5000 and I would like to know how much of this interval remains before the timer ticks. How I can do it?
How to check timer time?
You cannot. The timer classes offer no way check how long remains before a timer is due to fire. The best you can do is to keep track of when the timer last fired and calculate yourself how long remains before the next tick.
DateTime MainTimer_last_Tick = DateTime.Now;
System.Windows.Forms.Timer timer_Calc_Remaining;
timer_Calc_Remaining.Enabled = true;
timer_Calc_Remaining.Interval = 100;
timer_Calc_Remaining.Tick += new System.EventHandler(this.timer_Calc_Remaining_Tick);
on main timer start or tick:
timer_Main.Enabled = true;
MainTimer_last_Tick = DateTime.Now;
private void timer_Calc_Remaining_Tick(object sender, EventArgs e)
{
int remaining_Milliseconds = (int)(MainTimer_last_Tick.AddMilliseconds(timer_Main.Interval).Subtract(DateTime.Now).TotalMilliseconds);
.../*
int newValue = (timer_Main.Interval -remaining_Milliseconds) ;
progressBar1.Maximum = timer_Main.Interval+1;
progressBar1.Value = newValue ;*/
}
You could use an alternative timer with an interval of 1000 (milliseconds). I don't think an interval of 1ms is really an option as this will stress the system too much and is unreliable anyway.
Every time this timer elapses, you can check the number of ticks (is this always a multitude of 1000?) and subtract it from (or use modulo) 5000.
But I can't:
That's because less than sign comes before equal sign and not the other way round
Its <= not =<
if (timer1.Interval <= 5000)
{
//do something
}
You are using the Interval which is a property that will not be getting changed (It will always be 5000, so checking if it is smaller than 5000 is pointless). Also, if this code is in the Timer1_Tick function it will not be efficient. However, the code I believe you need is:
if (timer1.Interval <= 5000)
{
//do something
}

How to display updated time as system time on a label using c#?

I want to display current time on a label using C# but time will continuously change as system time changes. How can I do this?
Add a new Timer control to your form, called Timer1, set interval to 1000 (ms), then double click on the Timer control to edit the code-behind for Timer1_Tick and add this code:
this.label1.Text = DateTime.Now.ToString();
You can Add a timer control and specify it for 1000 millisecond interval
private void timer1_Tick(object sender, EventArgs e)
{
lblTime.Text = DateTime.Now.ToString("dd-MMM-yyyy hh:mm:ss tt");
}
Add a Timer control that is set to fire once every second (1000 ms). In that timer's Tick event, you can update your label with the current time.
You can get the current time using something like DateTime.Now.
Try the following code:
private void timer1_Tick(object sender, EventArgs e)
{
lblTime.Text = DateTime.Now.ToString("hh:mm:ss");
}
You must set the timer to be enabled also, either in code, or in the properties window.
in code, please type the following in the form load section:
myTimer.Enabled = true;
myTimer.Interval = 1000;
After that, make sure your timer event is similar to this:
private void myTimer_Tick(object sender, EventArgs e)
{
timeLabel.Text = DateTime.Now.ToString("hh:mm:ss");
}
Since the timer interval is not exact your update could be in bad sync and will be drifting with respect to the actual seconds transition. At some events you will lag behind or before the transition and miss updates in your time display
Instead of polling att high frequency to fire the update at the change of the seconds this method may grant you some respect.
If you like regulators you can adjust your time update to be safely located 100 ms after the actual second transition by adjusting the 1000 ms timer using the Millisecond property of the timestamp you want to display.
In the timer event code do something like this:
//Read time
DateTime time = DateTime.Now;
//Get current ms offset from prefered readout position
int diffms = time.Millisecond-100;
//Set a new timer interval with half the error applied
timer.Interval = 1000 - diffms/2;
//Update your time output here..
Next timer interval should then trigger closer to the selected point 100 ms after the seconds transition. When at the Transition+100ms the error will toggle +/- keeping your readout position in time.
private int hr, min, sec;
public Form2()
{
InitializeComponent();
hr = DateTime.UtcNow.Hour;
min = DateTime.UtcNow.Minute;
sec = DateTime.UtcNow.Second;
}
//Time_tick click
private void timer1_Tick(object sender, EventArgs e)
{
hr = DateTime.UtcNow.Hour;
hr = hr + 5;
min = DateTime.UtcNow.Minute;
sec = DateTime.UtcNow.Second;
if (hr > 12)
hr -= 12;
if (sec % 2 == 0)
{
label1.Text = +hr + ":" + min + ":" + sec;
}
else
{
label1.Text = hr + ":" + min + ":" + sec;
}
}

.NET, event every minute (on the minute). Is a timer the best option?

I want to do stuff every minute on the minute (by the clock) in a windows forms app using c#. I'm just wondering whats the best way to go about it ?
I could use a timer and set its interval to 60000, but to get it to run on the minute, I would have to enable it on the minute precisely, not really viable.
I could use a timer and set its interval to 1000. Then within its tick event, I could check the clocks current minute against a variable that I set, if the minute has changed then run my code. This worries me because I am making my computer do a check every 1 second in order to carry out work every 1 minutes. Surely this is ugly ?
I'm using windows forms and .Net 2.0 so do not want to use the DispatchTimer that comes with .Net 3.5
This must be a fairly common problem. Have any of you a better way to do this?
Building on the answer from aquinas which can drift and which doesn't tick exactly on the minute just within one second of the minute:
static System.Timers.Timer t;
static void Main(string[] args)
{
t = new System.Timers.Timer();
t.AutoReset = false;
t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
t.Interval = GetInterval();
t.Start();
Console.ReadLine();
}
static double GetInterval()
{
DateTime now = DateTime.Now;
return ((60 - now.Second) * 1000 - now.Millisecond);
}
static void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine(DateTime.Now.ToString("o"));
t.Interval = GetInterval();
t.Start();
}
On my box this code ticks consistently within .02s of each minute:
2010-01-15T16:42:00.0040001-05:00
2010-01-15T16:43:00.0014318-05:00
2010-01-15T16:44:00.0128643-05:00
2010-01-15T16:45:00.0132961-05:00
How about:
int startin = 60 - DateTime.Now.Second;
var t = new System.Threading.Timer(o => Console.WriteLine("Hello"),
null, startin * 1000, 60000);
Creating a Timer control that fires every 1 second (and usually does nothing but a simple check) will add negligible overhead to your application.
Simply compare the value of Environment.TickCount or DateTime.Now to the last stored time (the previous 'minute tick'), and you should have a reasonably precise solution. The resolution of these two time values is about 15ms, which should be sufficient for your purposes.
Do note however that the interval of the Timer control is not guaranteed to be that precise or even anywhere now, since it runs on the Windows message loop, which is tied in with the responsiveness of the UI. Never rely on it for even moderately precise timing - though it is good enough for firing repeating events where you can check the time using a more sensitive method such as one of the two given above.
You can nail this with reactive extensions which will take care of lots of timer related problems for you (clock changes, app hibernation etc). Use Nuget package Rx-Main and code like this:
Action work = () => Console.WriteLine(DateTime.Now.ToLongTimeString());
Scheduler.Default.Schedule(
// start in so many seconds
TimeSpan.FromSeconds(60 - DateTime.Now.Second),
// then run every minute
() => Scheduler.Default.SchedulePeriodic(TimeSpan.FromMinutes(1), work));
Console.WriteLine("Press return.");
Console.ReadLine();
Read here (search for "Introducing ISchedulerPeriodic") to see all the issues this is taking care of: http://blogs.msdn.com/b/rxteam/archive/2012/06/20/reactive-extensions-v2-0-release-candidate-available-now.aspx
I jsut wrote this class using the WPF DispatcherTimer but you can swap the dispatcher for any timer that supports changing when it's woken from sleep state.
The class is constructed with a fixed time step and supprts Start/Stop/Reset, Start/Stop/Start works like a resume operation. The timer is like a stopwatch in that regard.
A clock implementation would simply create the class with a interval of 1 second and listen to the event. Be wary though that this is a real-time clock, if the tick event takes longer than the interval to finish you'll notice that the clock will try and catch up to real-time this will cause a burst of tick events being raised.
public class FixedStepDispatcherTimer
{
/// <summary>
/// Occurs when the timer interval has elapsed.
/// </summary>
public event EventHandler Tick;
DispatcherTimer timer;
public bool IsRunning { get { return timer.IsEnabled; } }
long step, nextTick, n;
public TimeSpan Elapsed { get { return new TimeSpan(n * step); } }
public FixedStepDispatcherTimer(TimeSpan interval)
{
if (interval < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException("interval");
}
this.timer = new DispatcherTimer();
this.timer.Tick += new EventHandler(OnTimerTick);
this.step = interval.Ticks;
}
TimeSpan GetTimerInterval()
{
var interval = nextTick - DateTime.Now.Ticks;
if (interval > 0)
{
return new TimeSpan(interval);
}
return TimeSpan.Zero; // yield
}
void OnTimerTick(object sender, EventArgs e)
{
if (DateTime.Now.Ticks >= nextTick)
{
n++;
if (Tick != null)
{
Tick(this, EventArgs.Empty);
}
nextTick += step;
}
var interval = GetTimerInterval();
Trace.WriteLine(interval);
timer.Interval = interval;
}
public void Reset()
{
n = 0;
nextTick = 0;
}
public void Start()
{
var now = DateTime.Now.Ticks;
nextTick = now + (step - (nextTick % step));
timer.Interval = GetTimerInterval();
timer.Start();
}
public void Stop()
{
timer.Stop();
nextTick = DateTime.Now.Ticks % step;
}
}
Create a method or put this code where you want the timer to start:
int time = 60 - DateTime.Now.Second; // Gets seconds to next minute
refreshTimer.Interval = time * 1000;
refreshTimer.Start();
And then on your tick event set the interval to 60000:
private void refreshTimer_Tick(object sender, EventArgs e)
{
refreshTimer.Interval = 60000; // Sets interval to 60 seconds
// Insert Refresh logic
}
By making use of ReactiveExtensions you could use the following code if you were interested in doing something as simple as printing to the console.
using System;
using System.Reactive.Linq;
namespace ConsoleApplicationExample
{
class Program
{
static void Main()
{
Observable.Interval(TimeSpan.FromMinutes(1))
.Subscribe(_ =>
{
Console.WriteLine(DateTime.Now.ToString());
});
Console.WriteLine(DateTime.Now.ToString());
Console.ReadLine();
}
}
}
Running a bit of code to see if the minute has changed once per second should not require much CPU time, and should be acceptable.
What about Quartz.NET? I think its a good framework to do timed actions.
You could set up two timers. An initial short interval timer (perhaps to fire every second, but dependent on how presice the second timer must fire on the minute).
You would fire the short interval timer only until the desired start time of the main interval timer is reached. Once the initial time is reached, the second main interval timer can be activated, and the short interval timer can be deactivated.
void StartTimer()
{
shortIntervalTimer.Interval = 1000;
mainIntervalTimer.Interval = 60000;
shortIntervalTimer.Tick +=
new System.EventHandler(this.shortIntervalTimer_Tick);
mainIntervalTimer.Tick +=
new System.EventHandler(mainIntervalTimer_Tick);
shortIntervalTimer.Start();
}
private void shortIntervalTimer_Tick(object sender, System.EventArgs e)
{
if (DateTime.Now.Second == 0)
{
mainIntervalTimer.Start();
shortIntervalTimer.Stop();
}
}
private void mainIntervalTimer_Tick(object sender, System.EventArgs e)
{
// do what you need here //
}
Alternatively, you could sleep to pause execution until it times out which should be close to your desired time. This will only wake the computer when the sleep finishes so it'll save you CPU time and let the CPU power down between processing events.
This has the advantage of modifying the timeout so that it will not drift.
int timeout = 0;
while (true) {
timeout = (60 - DateTime.Now.Seconds) * 1000 - DateTime.Now.Millisecond;
Thread.Sleep(timeout);
// do your stuff here
}
Use a timer set to run every second (or millisecond, whatever your accuracy threshold is), and then code the method to run your functionality if and only if the current time is within that threshold past the "on the minute" point.
What I'm using for scheduled tasks is a System.Threading.Timer(System.Threading.TimerCallback, object, int, int) with the callback set to the code I want to execute based on the interval which is supplied in milliseconds for the period value.
What about a combination of aquinas' answer and 'polling': (apologies for the mixture of languages)
def waitForNearlyAMinute:
secsNow = DateTime.Now.Second;
waitFor = 55 - secsNow;
setupTimer(waitFor, pollForMinuteEdge)
def pollForMinuteEdge:
if (DateTime.Now.Second == 0):
print "Hello, World!";
waitForNearlyAMinute();
else:
setupTimer(0.5, pollForMinuteEdge)
I have a solution based on Environment.TickCount
static void Main(string[] args)
{
//constatnt total miliseconds to one minute
const Int32 minuteMilisecond = 60 * 1000;
//get actual datetime
DateTime actualDateTime = DateTime.UtcNow;
//compenzation to one minute
Int32 nexTimer = Environment.TickCount + ((59 - actualDateTime.Second) * 1000) + (999 - actualDateTime.Millisecond);
//random fuction to simulate different delays on thread
Random rnd = new Random();
//main loop
while (true)
{
if (Environment.TickCount > nexTimer)
{
nexTimer += minuteMilisecond;
//execute your code here every minute
Console.WriteLine($"actual DateTime: {DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss:ffff")}");
}
//random sleep between 100 - 200 ms
Thread.Sleep(rnd.Next(100, 200));
}
}

Categories