I try to create in windows phone timer which update every 10-15 ms (for UI element). And i want have opportunity to append time. So i create TimeSpan and DispatcherTimer where interval = 15 ms. So every 15 ms call the event where i subtract 15 ms to timeSpan and when timespan <= 0 i call some method. When i set TimeSpan 4 seconds (for example) in life passed more than 4 sec about 4,6 sec. Also i tryed to use async/await but this did't work. I tryed to use System.Threading but i don't know how to update element which was create in the other thread.
So every 15 ms call the event where i subtract 15 ms to timeSpan and when timespan <= 0 i call some method.
Your logic is flawed. You can't possibly update your timespan this way because:
As Stephen Cleary mentioned in his answer, you have no guarantee that the timer will fire at exactly 15 ms
Even if it did, it doesn't take into account the time needed to actually update your timespan (say that it takes 1ms to compute the new timespan, your timer will drift of 1ms every 15ms)
To have an accurate time, you need to store the timestamp at which you started it (retrieve it by using DateTime.UtcNow. Every time your timer tick, take the new timestamp and substract to the one you saved. This way, you know exactly how much time has passed and your timer will never drift.
private DateTime start; // Set this with DateTime.UtcNow when starting the timer
void timer_Tick(object sender, EventArgs e)
{
// Compute the new timespan
var timespan = DateTime.UtcNow - start;
// Do whatever with it (check if it's greater than 4 seconds, display it, ...)
}
So every 15 ms call the event where i subtract 15 ms to timeSpan
And there's your problem.
When you set a timer on any Windows platform, you can't expect a huge level of precision. On the desktop I believe the normal scheduler period on consumer hardware is ~12ms (and of course other apps can throw that off considerably). I have no idea what the scheduling is like on the phone but I assume it's less accurate than desktop (for battery lifetime reasons).
So, you simply can't approach this problem that way on Windows, because you can't assume that a timer will fire every 15ms. Instead, just start the DispatcherTimer to the full time span that you need, e.g., 4 seconds.
Try this to update UI element in your timer thread
Dispatcher.BeginInvoke(() =>
{
//Update Your Element.
});
Related
I've been tasked with writing a method that calculates, given a start datetime and timeout in minutes, the datetime that the timeout should occur.
However the timeout should only 'tick' during certain times on certain days, which is determined by a non tick start datetime, non tick stop datetime and a list of open days.
For example, given the following:
Start datetime: Friday 21/02/2014 15:00
Timeout: 720 minutes (12 hours)
Open days: Monday,Tuesday,Wednesday,Thursday,Friday
Non tick start time: 09:00
Non tick stop time: 18:30
The calculated timeout datetime should be Monday 24/02/2014 17:30 (as it does not tick on Saturday and Sunday).
I'm writing this in C#, but its technically language agnostic.
Is there an 'elegant' way of doing this? Or is it simply a case of looping and adding additional time where its determined that timeout should stop ticking?
If you set up a timer to tick every period (e.g. every second), you can increment a number of ticks in the timer's callback handler.
I would approach in one of the following ways. Either I could run the callback every second no matter what, and in the callback I could check whether I'm suppose to increment or skip the increment for this period (inside the non-tick time period).
Otherwise, I could increment every time no matter what, and then have a check to see if the non-tick period is approaching and, if so, then adjust the timer's callback time to run the next callback after the non-tick time period has elapsed.
I am working on a project that allows me to create a program and give it tasks. Right now I am working on where I can tell it to set an alarm. The alarm feature works well, but I have a problem. When I set the alarm, I can say "goodnight" and then the program turns my monitor off into sleep mode. When the alarm goes off I want it to turn the monitor back on 10 or 15 seconds before it executes the code that happens when the alarm goes off.
Here is a bit of my code:
DateTime now = DateTime.Now;
string time = now.GetDateTimeFormats('t')[0];
if (time == Settings.Default.Alarm && Settings.Default.AClockEnbl == true)
{
SetMonitorInState(MonitorState.MonitorStateOn);
}
if (time == Settings.Default.Alarm && Settings.Default.AClockEnbl == true)
{
//All other alarm code
}
I want the first if statement to tell the command to happen 10 seconds before Settings.Default.Alarm
Can anybody help?
If you add 15 seconds to the DateTime now and compare that to the Alarm time, you can use that to turn on the monitor.
Then you can execute the rest of the code when now (without the extra 15 seconds) equals the alarm time.
As mentioned in comments you'll want to compare with DateTime's instead of strings and use TimeSpan to increment 15 seconds.
You can use a TimeSpan to offset your date:
beforeTime = now + TimeSpan.FromSeconds(15);
then compare Settings.Default.Alarm with beforeTime.GetDateTimeFormats('t')[0] in order to turn on the monitor.
This said, try to refactor your code and get rid of those strings. Use DateTime and TimeSpan or ms since Epoch in an int if you really want, but not strings.
I have a windows service and I would like to insert a timer. How can I check if the present time is 9:00 AM ?
I would like my service to check this every day. Thank you a lot
My try:
Datetime dt=Datetime.parse("09:00:00 everyday");
if(datetime.now -dt ==0)
{
//fire event
}
Thats kinda sily of me though.
You need to make a timer and sets its interval to the timespan between now and tomorrow 9:00 AM. Next time the timer tick, set the interval again in the same way.
You should use this Timer class:
http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
Please use DateTime.UtcNow.Hour to check current hour
By using UtcNow you will gets a DateTime object that is set to the current date and time on the computer, expressed as the Coordinated Universal Time (UTC).
var now = DateTime.Now;
var today = now.Date;
var nineAm = today.AddHours(9);
TimeSpan ts = nineAm - now;
var timeInMillisecondsTill9Am = ts.Milliseconds;
If(timeInMillisecondsTill9Am==0)
{
//your code goes here
}
Since you don't know when someone may shutdown or reboot your computer or service then you need to make sure that you use a method robust enough to handle these kinds of interruptions.
I suggest that when your service checks every 5 minutes or so if the time is after 9am and if the last run date is yesterday. If so, you update the last run date to day (perhaps in a simple text file) and then run the "9:00am" task. In this way your task only runs once per day, fairly close to 9am, and is robust against reboots.
You'll need to use a standard .NET timer to trigger the checks - and if you're clever enough you can make it fire a few seconds after 9am.
Let me know if that's a good solution.
I am using System.Timer to trigger an event. Currently I trigger it every 1 hour and check if it matches the configured value (day,time).
But it is possible to trigger this at a specific time? like suppose on Sunday at 12Am.
Windows Task Scheduler would be more appropriate but its not an option.
Thanks in advance
It isn't clear why you just wouldn't set the timer's Interval to the target date/time. There's a limit on the number of milliseconds, you can time up to 2^31 milliseconds, 27 days. You'll be good as long as you can stay in that range.
private static void SetTimer(Timer timer, DateTime due) {
var ts = due - DateTime.Now;
timer.Interval = ts.TotalMilliseconds;
timer.AutoReset = false;
timer.Start();
}
The timer doesn't support this kind of interval but you could check every 20 seconds for the current day and time.
Edit Sorry you are doing that already... why not make the interval half the time left each time you check (A Zeno timer)?
In a similar situation, I'm using System.Threading.Timer to achieve this. Basically I set its due time to desiredDateTime - DateTime.Now, so that it will tick at desiredDateTime.
If you get another date meanwhile, you can user Timer.Change() to change the tick time to the new date. Don't forget to Dispose() the Timer when you no longer need it!
I'm developing an application and I need to get the current date from a server (it differs from the machine's date).
I receive the date from the server and with a simple Split I create a new DateTime:
globalVars.fec = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, int.Parse(infoHour[0]), int.Parse(infoHour[1]), int.Parse(infoHour[2]));
globalVars is a class and fec is a public static variable so that I can access it anywhere in the application (bad coding I know...).
Now I need to have a timer checking if that date is equal to some dates I have stored in a List and if it is equal I just call a function.
List<DateTime> fechas = new List<DateTime>();
Before having to obtain the date from a server I was using computer's date, so to check if the dates matched I was using this:
private void timerDatesMatch_Tick(object sender, EventArgs e)
{
DateTime tick = DateTime.Now;
foreach (DateTime dt in fechas)
{
if (dt == tick)
{
//blahblah
}
}
}
Now I have the date from the server so DateTime.Now can't be used here. Instead I have created a new timer with Interval=1000 and on tick I'm adding 1 second to globalVars.fec using:
globalVars.fec = globalVars.fec.AddSeconds(1);
But the clock isn't accurate and every 30 mins the clock loses about 30 seconds.
Is there another way of doing what I'm trying to do? I've thought about using threading.timer instead but I need to have access to other threads and non-static functions.
Store the difference between the server's time and local time. Calculate the servers' time when you need it using that difference.
If you create atimer with an interval of 1000ms, it will be called no sooner than 1000ms. So you can pretty much guarantee that it will be called in more than 1000ms, which means you will "lose" time by adding 1s on this timer tick - This will accumulate error with every tick. A better approach is to record a start time and use the current time to determine the current offset from that known start time, so that you don't accumulate any error in your time keeping. (There will still be some error, but you will not drift out of touch with real-time over time)
Different timers (Forms.Timer, Thread.Timer etc) will give different accuracies as well - Forms.Timer is particularly poor for accuracy.
You could also use a high performance time to keep track of the time better - see here, for example.
Here is a reliable 1 μs Timer
See https://stackoverflow.com/questions/15725711/obtaining-microsecond-precision-using-net-without-platform-invoke?noredirect=1#comment22341931_15725711
I guarantee its faster and more accurate then StopWatch and PerformanceCounters and uses the fractions of a second you have in the time slice wisely!