reset the timer on second call - c#

I am bit New here ...and learning Threading.Timer ... I have a timer in Window Service which fires a function at 16:48:00 ..I just want to Fire the Timer Again at 21:00:00 PM ...then 22:00:00 ...there is no fix timer interval between the timeslots
here is My Code what I have Tried:
public partial class ASMSService1 : ServiceBase
{
private Timer myTimer;
private DateTime inputDate;
private DateTime yesterday;
private DateTime today;
public ASMSService1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
inputDate = DateTime.Today;
today = DateTime.Today;
yesterday = today.AddDays(-1);
//time is Set here
SetTimer(16, 48, 00);
}
private void SetTimer(int hours, int minutes, int seconds)
{
inputDate = DateTime.Today.AddHours(hours).AddMinutes(minutes).AddSeconds(seconds);
String date1 = inputDate.TimeOfDay.ToString();
if (DateTime.Now > inputDate)
{
inputDate = inputDate.AddDays(1);
}
if (date1.CompareTo("16:48:00") == 0)
{
myTimer = new System.Threading.Timer(new TimerCallback(FirstSlotOperations));
myTimer.Change((int)(inputDate - DateTime.Now).TotalMilliseconds, Timeout.Infinite);
}
}
private void FirstSlotOperations(object e)
{
//some operation
//Need to reset the Timer at 21:00:00
}
}
I have found the timer.change From MSDN article ..But I am not sure How to implement it in my case
I have Tried Thread.sleep()..But I am looking for some alternative also if possible ..
any suggestion would be Helpful

I think Artyom Kharlamov is right, if you provide more details about what specific functionality do you intend to achieve, there is a better chance to get an answer that is closer to what you need.
My take on what you have currently presented:
If you want the service to perform a specific operation whenever the time of the day is equal to a predefined value (for example 16:48 as per your provided code), i think your approach is kind of complicated since you could achieve this easier by using Scheduled Tasks, which will also cover the case in which you're trying to perform an operation within your service not on a specific time of the day but every x amount of time.
The timer object doesn't seem to expose any property or method that will tell you how much time has ellapsed since it first started ticking, for that you can use properties and get the current time whenever SetTimer is called, set a property in the ASMSService1 class and get the difference with the current time when FirstSlotOperations is called.
Maybe this isn't exactly what you want to do but unless you get a little more specific about your expectations it's hard to address them efficiently.

You don't need any object to get current time. Just use:
private void FirstSlotOperations(object e)
{
DateTime current = DateTime.Now;
}
An object passed as an argument in callback function is timer object so you can't get data from it. You can use it only to operate on timer object for example.
private void FirstSlotOperations(object e)
{
Timer t = e as Timer;
t.Change(1000, 0);
}

Related

Timer resets after 60 seconds

Below is the code that I'm attempting to use as an elapsed timer on a desktop task timer that we're building. Right now when this runs it only counts to 60 seconds and then resets and doesn't ever add to the minutes.
//tick timer that checks to see how long the agent has been sitting in the misc timer status, reminds them after 5 mintues to ensure correct status is used
private void statusTime_Tick(object sender, EventArgs e)
{
counter++;
//The timespan will handle the push from the elapsed time in seconds to the label so we can update the user
//This shouldn't require a background worker since it's a fairly small app and nothing is resource heavy
var timespan = TimeSpan.FromSeconds(actualTimer.Elapsed.Seconds);
//convert the time in seconds to the format requested by the user
displaycounter.Text=("Elapsed Time in " + statusName+" "+ timespan.ToString(#"mm\:ss"));
//pull the thread into updating the UI
Application.DoEvents();
}
Quick Fix
I believe the problem is that you are using Seconds which is 0-59. You want to use TotalSeconds with your existing code:
var timespan = TimeSpan.FromSeconds(actualTimer.Elapsed.TotalSeconds);
Comments
However, this doesn't make a lot of sense as you could just use the TimeSpan object directly:
var timespan = actualTimer.Elapsed;
Also, I can't see all your application, but I would expect you do not need to call Application.DoEvents();. As the UI should update automatically when it has the chance... if it doesn't then you want to look at moving whatever code is blocking the UI to a different thread.
Recommendation
With all that said, I would recommend you don't use a timer to track elapsed time at all. Timers can lose accuracy over time. The best approach is to store the current system time when you start the process, then when you need to display the 'timer' do an on-demand calculation at that point.
A very simple example to help explain what I mean:
DateTime start;
void StartTimer()
{
start = DateTime.Now;
}
void UpdateDisplay()
{
var timespan = DateTime.Now.Subtract(start);
displaycounter.Text = "Elapsed Time in " + statusName + " " + timespan.ToString(#"mm\:ss"));
}
You could then use a timer to call your UpdateDisplay method at regular intervals:
void statusTime_Tick(object sender, EventArgs e)
{
UpdateDisplay();
}

Run code at a certain time [duplicate]

I have a service written in C# (.NET 1.1) and want it to perform some cleanup actions at midnight every night. I have to keep all code contained within the service, so what's the easiest way to accomplish this? Use of Thread.Sleep() and checking for the time rolling over?
I wouldn't use Thread.Sleep(). Either use a scheduled task (as others have mentioned), or set up a timer inside your service, which fires periodically (every 10 minutes for example) and check if the date changed since the last run:
private Timer _timer;
private DateTime _lastRun = DateTime.Now.AddDays(-1);
protected override void OnStart(string[] args)
{
_timer = new Timer(10 * 60 * 1000); // every 10 minutes
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
_timer.Start();
//...
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// ignore the time, just compare the date
if (_lastRun.Date < DateTime.Now.Date)
{
// stop the timer while we are running the cleanup task
_timer.Stop();
//
// do cleanup stuff
//
_lastRun = DateTime.Now;
_timer.Start();
}
}
Check out Quartz.NET. You can use it within a Windows service. It allows you to run a job based on a configured schedule, and it even supports a simple "cron job" syntax. I've had a lot of success with it.
Here's a quick example of its usage:
// Instantiate the Quartz.NET scheduler
var schedulerFactory = new StdSchedulerFactory();
var scheduler = schedulerFactory.GetScheduler();
// Instantiate the JobDetail object passing in the type of your
// custom job class. Your class merely needs to implement a simple
// interface with a single method called "Execute".
var job = new JobDetail("job1", "group1", typeof(MyJobClass));
// Instantiate a trigger using the basic cron syntax.
// This tells it to run at 1AM every Monday - Friday.
var trigger = new CronTrigger(
"trigger1", "group1", "job1", "group1", "0 0 1 ? * MON-FRI");
// Add the job to the scheduler
scheduler.AddJob(job, true);
scheduler.ScheduleJob(trigger);
A daily task? Sounds like it should just be a scheduled task (control panel) - no need for a service here.
Does it have to be an actual service? Can you just use the built in scheduled tasks in the windows control panel.
The way I accomplish this is with a timer.
Run a server timer, have it check the Hour/Minute every 60 seconds.
If it's the right Hour/Minute, then run your process.
I actually have this abstracted out into a base class I call OnceADayRunner.
Let me clean up the code a bit and I'll post it here.
private void OnceADayRunnerTimer_Elapsed(object sender, ElapsedEventArgs e)
{
using (NDC.Push(GetType().Name))
{
try
{
log.DebugFormat("Checking if it's time to process at: {0}", e.SignalTime);
log.DebugFormat("IsTestMode: {0}", IsTestMode);
if ((e.SignalTime.Minute == MinuteToCheck && e.SignalTime.Hour == HourToCheck) || IsTestMode)
{
log.InfoFormat("Processing at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute);
OnceADayTimer.Enabled = false;
OnceADayMethod();
OnceADayTimer.Enabled = true;
IsTestMode = false;
}
else
{
log.DebugFormat("Not correct time at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute);
}
}
catch (Exception ex)
{
OnceADayTimer.Enabled = true;
log.Error(ex.ToString());
}
OnceADayTimer.Start();
}
}
The beef of the method is in the e.SignalTime.Minute/Hour check.
There are hooks in there for testing, etc. but this is what your elapsed timer could look like to make it all work.
As others already wrote, a timer is the best option in the scenario you described.
Depending on your exact requirements, checking the current time every minute may not be necessary.
If you do not need to perform the action exactly at midnight, but just within one hour after midnight, you can go for Martin's approach of only checking if the date has changed.
If the reason you want to perform your action at midnight is that you expect a low workload on your computer, better take care: The same assumption is often made by others, and suddenly you have 100 cleanup actions kicking off between 0:00 and 0:01 a.m.
In that case you should consider starting your cleanup at a different time. I usually do those things not at clock hour, but at half hours (1.30 a.m. being my personal preference)
I would suggest that you use a timer, but set it to check every 45 seconds, not minute. Otherwise you can run into situations where with heavy load, the check for a particular minute is missed, because between the time the timer triggers and the time your code runs and checks the current time, you might have missed the target minute.
You can also try the TaskSchedulerLibrary here http://visualstudiogallery.msdn.microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8
Implement the abstract class AbstractScheduledTask and call the ScheduleUtilityFactory.AddScheduleTaskToBatch static method
For those that found the above solutions not working, it's because you may have a this inside your class, which implies an extension method which, as the error message says, only makes sense on a non-generic static class. Your class isn't static. This doesn't seem to be something that makes sense as an extension method, since it's acting on the instance in question, so remove the this.
Try this:
public partial class Service : ServiceBase
{
private Timer timer;
public Service()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
SetTimer();
}
private void SetTimer()
{
if (timer == null)
{
timer = new Timer();
timer.AutoReset = true;
timer.Interval = 60000 * Convert.ToDouble(ConfigurationManager.AppSettings["IntervalMinutes"]);
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
}
private void timer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
{
//Do some thing logic here
}
protected override void OnStop()
{
// disposed all service objects
}
}

Schedule a daily event on a program that runs all day

I am coding a C# WinForms program that I want to have running in the background 24/7. In an XML file, I'm pulling a time. For example: 3:30:00 PM. When I then display this time after parsing it, it comes out as 1/15/2014 3:30:00 PM.
What my question is, based on this XML value, how can I have it so that, at 3:30:00 PM every day, a Timer object or something displays a message box or some other action?
Your idea of using a Timer is good. You could use either the Winforms Timer or System.Timers.Timer. In this case, I will refer to System.Timers.Timer as I have some code I can base this answer off of.
Anyway, just assign it an Interval and give an event to fire via Elapsed. Then in the code that Elapsed calls, put in your action code. Finally, start the timer wherever you need it and try running it.
If you are using a DateTime to hold the file data, then you will need to either create a constant number of milliseconds until the next day (not recommended), or do some math using TimeSpans (hint: use the constructor to get the time). The TimeSpan contains a property called 'TotalMilliseconds' that you can use as the Interval.
I hope this points you in the right direction.
That is a console application that executes a job at a fixed time every day
using System;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
public static void Main()
{
Timer t = new Timer(TimerCallback, null, 0, 2000);
// Wait for the user to hit <Enter>
Console.ReadLine();
}
private static void TimerCallback(Object o)
{
Console.WriteLine("In TimerCallback: " + DateTime.Now);
DateTime s = DateTime.Now;
TimeSpan ts = new TimeSpan(23, 27, 0);
s = s.Date + ts;
if (DateTime.Now > s && !fired)
{
Console.WriteLine("Do the Job");
fired = true;
}
else if (DateTime.Now < s)
{
fired = false;
}
}
private static bool fired = false;
}
}

Accurate method to track time

For my application, I've to track the time change, to "smooth" the time change.
A system time change can occurs for several reasons:
The user change its system time
The OS NTP Server updates the local time
...
So actually we have a "TimeProvider", which provide to the whole application the current time.
The goal is to detect if a time shift occurs and correct our local time smoothly(like, if we have a "time jump" of one hour, correct 100ms every second until this is fully corrected).
Here is basically what I've to provide the time(please note that currently I absolutely don't smooth the time change, but not my current issue)
internal class TimeChange : IDisposable
{
private readonly Timer _timer;
private readonly Stopwatch _watch = new Stopwatch();
private DateTime _currentTime;
public DateTime CurrentTime
{
get { return _currentTime + _watch.Elapsed; }
}
public TimeChange()
{
_timer = new Timer(1000);
_timer.Elapsed += OnTimerElapsed;
_timer.Start();
_watch.Start();
_currentTime = DateTime.UtcNow;
}
public void Dispose()
{
_timer.Stop();
_timer.Elapsed -= OnTimerElapsed;
}
private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
DateTime currentTime = DateTime.UtcNow;
TimeSpan timeDerivation = currentTime - _currentTime - _watch.Elapsed;
_watch.Restart();
_currentTime = currentTime;
Console.WriteLine("Derivation: " + timeDerivation.TotalMilliseconds + "ms");
}
}
But when doing some test, I noticed that I've differences even without doing anything on my local time. Not huge differences(<1ms), but still:
Press enter to stop
Derivation: -0.1367ms
Derivation: 0.9423ms
Derivation: 0.0437ms
Derivation: 0.0617ms
Derivation: 0.0095ms
Derivation: 0.0646ms
Derivation: -0.0149ms
And this is derivation for 1 second, if I just replace the 1000ms by 10000ms, I quickly have a time derivation between 1ms and 0.5ms.
So my question(Finally :P):
Why between two Utc.DateTime gave me so much differences? They are both based on clock Tick no?
Isn't there a way to get this time shift more precisely ?
No they are not both based on clock tick. Stopwatch maybe either high or low res. If low res, then it uses DateTime.UtcNow underneith. Unfortuantely you cannot choose if it's high or low, so:
Create own "Stopwatch" that always uses DateTime.UtcNow underneith.
EDIT
That's a stupid suggestion in (2.), you obviously need to avoid DateTime.UtcNow as that's what you are trying to correct. I suggest you look at working in ticks, by which I mean 1/10000 of a second, to match high-res Stopwatch. This is because TimeSpan is only accurate to 1/1000 of a second.
Number 1. in more detail:
Stopwatch uses this method:
public static long GetTimestamp()
{
if (!Stopwatch.IsHighResolution)
{
DateTime utcNow = DateTime.UtcNow;
return utcNow.Ticks; //There are 10,000 of these ticks in a second
}
else
{
long num = (long)0;
SafeNativeMethods.QueryPerformanceCounter(out num);
return num; //These ticks depend on the processor, and
//later will be converted to 1/10000 of a second
}
}
But like I say, IsHighResolution appears to be not settable and as a static applies system wide anyway, so write your own.

How can I add a timer on Windows Phone 7.1?

I'm looking for a way to add a timer (or stopwatch) that will start counting from 0 the moment the application is launched or a button is clicked, and keeps counting even after the user navigates through different pages, and then be able to display how much time has passed in the last page of the application. I've been messing around with the DispatcherTimer class, but to be honest, I'm having trouble understanding it. Any help, or even a nod in the right direction would be greatly appreciated!
If you want to use a time, you could add one on the page showing time!
Add this code to the constructor or somewhere else where you want to activate the timer. (The App.StartTime is the same as i wrote in the other answer)
DispatcherTimer timer = new DispatcherTimer();
timer.Tick +=
delegate(object s, EventArgs args)
{
TimeSpan time = (DateTime.Now - App.StartTime);
this.timenow.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", time.Hours, time.Minutes, time.Seconds);
};
timer.Interval = new TimeSpan(0, 0, 1); // one second
timer.Start();
You just have to store the time when your app launch and then subtract the current time from the stored value.
in your App.cs store the time when application launch:
private static DateTime _starttime = DateTime.Now;
public static DateTime StartTime
{
get
{
return _starttime;
}
}
In your page or any where you need to get the current time the application has run, you just have to subtract then current time from the stored time. I have used it in a button click handler, see below:
private void timebutton_Click(object sender, RoutedEventArgs e)
{
TimeSpan time = (DateTime.Now - App.StartTime);
this.timenow.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", time.Hours, time.Minutes, time.Seconds);
}

Categories

Resources