I have a program written in C#. I want the Timer class to run a function at a specific time.
E.g : run function X at 20:00 PM
How can I do that using the Timer class?
Good way of firing an event at a particular time of day?
Use the Timer Tick event to check (Set the tick to a suitable value) then in the tick event:
DateTime Now = DateTime.Now;
if(Now.Hours == DateTimeCallX.Hours
&& Now.Minutes == DateTimeCallX.Minutes
&& xHasRan == false)
{
x();
xHasRan = true;
}
DateTimeCallX being a DateTime object set to 20:00.
xHasRan is a boolean stating whether the function has been called, this will be initially set to false and set to true after x has been called so that if the timer tick runs again in the same minute then it won't run the function again.
When the timer fires, check the time and whether the function has run that day. If the time is after 20:00 and the function hasn't been called, call it. Otherwise, exit and wait for the next event.
Also, keep in mind that the forms timer and System.Threading.Timer work slightly differently.
You would have to calculate the number of milliseconds until 20:00 PM or use a scheduler like Quartz.NET.
Set the timer to run a method that checks what time it is, and run your code if the desired time has past, or goes back to sleep for FEW MILLISECONDS IF IT HAS NOT.
Related
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.
});
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!