How to set timer to execute at specific time in c# - c#

I have a requirement where i need to execute timer at 00:01:00 A.M every day...But i am not getting how to achieve this ..If i am taking Systems time,it can be in different format..
Here is my timer code..
static System.Timers.Timer timer;
timer = new System.Timers.Timer();
timer.Interval = 1000 * 60 * 60 * 24;//set interval of one day
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
start_timer();
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
// Add timer code here
}
private static void start_timer()
{
timer.Start();
}

If you want to start a timer at exactly 00:01:00am do some processing time and then restart the timer you just need to calculate the difference between Now and the next 00:01:00am time slot such as.
static Timer timer;
static void Main(string[] args)
{
setup_Timer();
}
static void setup_Timer()
{
DateTime nowTime = DateTime.Now;
DateTime oneAmTime = new DateTime(nowTime.Year, nowTime.Month, nowTime.Day, 0, 1, 0, 0);
if (nowTime > oneAmTime)
oneAmTime = oneAmTime.AddDays(1);
double tickTime = (oneAmTime - nowTime).TotalMilliseconds;
timer = new Timer(tickTime);
timer.Elapsed += timer_Elapsed;
timer.Start();
}
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
timer.Stop();
//process code..
setup_Timer();
}

What you should do is write your program that does whatever you need it to do, and then use your OS's built-in task scheduler to fire it off. That'd be the most reliable. Windows's Task Scheduler, for instance, can start your app before the user logs in, handle restarting the app if necessary, log errors and send notifications, etc.
Otherwise, you'll have to run your app 24/7, and have it poll for the time at regular intervals.
For instance, you could change the interval every minute:
timer.Interval = 1000 * 60;
And inside your Elapsed event, check the current time:
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (DateTime.Now.Hour == 1 && DateTime.Now.Minute == 0)
{
// do whatever
}
}
But this is really unreliable. Your app may crash. And dealing with DateTime's can be tricky.

You could always calculate it:
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
// Do stuff
start_timer();
}
private static void start_timer()
{
timer.Interval = CalculateInterval();
timer.Start();
}
private static double CalculateInterval()
{
// 1 AM the next day
return (DateTime.Now.AddDays(1).Date.AddHours(1) - DateTime.Now).TotalMilliseconds;
}

Here is a timer implementation which takes an Interval (just like any other timer) and fires exactly when that interval expires, even the machine goes to sleep mode in between.
public delegate void TimerCallbackDelegate(object sender, ElapsedEventArgs e);
public class TimerAbsolute : System.Timers.Timer
{
private DateTime m_dueTime;
private TimerCallbackDelegate callback;
public TimerAbsolute(TimerCallbackDelegate cb) : base()
{
if (cb == null)
{
throw new Exception("Call back is NULL");
}
callback = cb;
this.Elapsed += this.ElapsedAction;
this.AutoReset = true;
}
protected new void Dispose()
{
this.Elapsed -= this.ElapsedAction;
base.Dispose();
}
public double TimeLeft
{
get
{
return (this.m_dueTime - DateTime.Now).TotalMilliseconds;
}
}
public int TimeLeftSeconds
{
get
{
return (int)(this.m_dueTime - DateTime.Now).TotalSeconds;
}
}
public void Start(double interval)
{
if (interval < 10)
{
throw new Exception($"Interval ({interval}) is too small");
}
DateTime dueTime = DateTime.Now.AddMilliseconds(interval);
if (dueTime <= DateTime.Now)
{
throw new Exception($"Due time ({dueTime}) should be in future. Interval ({interval})");
}
this.m_dueTime = dueTime;
// Timer tick is 1 second
this.Interval = 1 * 1000;
base.Start();
}
private void ElapsedAction(object sender, System.Timers.ElapsedEventArgs e)
{
if (DateTime.Now >= m_dueTime)
{
// This means Timer expired
callback(sender, e);
base.Stop();
}
}
}

Related

Measuring code execution while showing time elapsed every second in C#

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.
}

Windows Service run every hour in specific minute

I need help.
I have Windows Service and I need run this service every hour in specific minute for example: 09:05, 10:05, 11:05,....
My service now start every hour but every hour from time when i start this service.
So how can I achieve my needs.
My code:
public partial class Service1 : ServiceBase
{
System.Timers.Timer timer = new System.Timers.Timer();
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
this.WriteToFile("Starting Service {0}");
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 60000;
timer.Enabled = true;
}
protected override void OnStop()
{
timer.Enabled = false;
this.WriteToFile("Stopping Service {0}");
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
this.WriteToFile(" interval start {0}");
} }
You should check current time every 'n' seconds (1 as example) from timer:
public partial class Service1 : ServiceBase
{
System.Timers.Timer timer = new System.Timers.Timer();
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
this.WriteToFile("Starting Service {0}");
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 1000; // 1000 ms => 1 second
timer.Enabled = true;
}
protected override void OnStop()
{
timer.Enabled = false;
this.WriteToFile("Stopping Service {0}");
}
private int lastHour = -1;
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
var curTime = DateTime.Now; // Get current time
if (lastHour != curTime.Hour && curTime.Minute == 5) // If now 5 min of any hour
{
lastHour = curTime.Hour;
// Some action
this.WriteToFile(" interval start {0}");
}
}
}
Here's another way you can calculate the first interval:
var minutesAfterHourToStart = 5; // Start at 5 minutes after the hour
var now = DateTime.Now;
var minutesToStart = 60 - (now.Minute - (minutesAfterHourToStart - 1));
if (minutesToStart > 60) minutesToStart -= 60;
var secondsToStart = 60 - now.Second + (minutesToStart * 60);
timer.Interval = TimeSpan.FromSeconds(secondsToStart).TotalMilliseconds;
Then, in the OnTimeElapsed event, you would set the interval to run every hour. To prevent constantly setting the variable to the same value over and over, we could set a global variable that we've already set the final interval:
class MyService
{
private bool resetInterval = true;
Then we can check this and set it to false the first time through:
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
if (resetInterval)
{
timer.Interval = TimeSpan.FromHours(1).TotalMilliseconds;
resetInterval = false;
}
Maybe just leave your code like it is, and set your service to start manually, then use windows scheduler to start it one time at specific hour. The rest work will do timer and OnElapse method;
This could help you: https://stackoverflow.com/a/36309450/5358389
You have all you need just start the timer differently:
public partial class Service1 : ServiceBase
{
System.Timers.Timer timer = new System.Timers.Timer();
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
this.WriteToFile("Starting Service {0}");
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
var excess = DateTime.Now.Minute - 5;
var span = DateTime.Now.AddMinutes(excess <= 0 ? -excess : 60- excess) - DateTime.Now;
timer.Interval = span.TotalMilliseconds;
timer.Enabled = true;
}
protected override void OnStop()
{
timer.Enabled = false;
this.WriteToFile("Stopping Service {0}");
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
var excess = DateTime.Now.Minute - 5;
var span = DateTime.Now.AddMinutes(excess <= 0 ? -excess : 60- excess) - DateTime.Now;
timer.Interval = span.TotalMilliseconds;
this.WriteToFile(" interval start {0}");
}
}
This way you set for the first "x:05" minute and then every hour.

Running the windows service for every one minute

I have tried to run the service every 1 minute and i have succeeded in doing so but the problem is its starting every minute regardless of the completion of the program. I have written it like this
private Timer _timer;
private DateTime _lastRun = DateTime.Now.AddDays(-1);
public SpotlessService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
_timer = new Timer(1 * 60 * 1000); // every 1 hour
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
_timer.Start();
}
public void Start()
{
OnStart(new string[0]);
}
void timer_Elapsed(object sender, EventArgs e)
{
Util.LogError("Started at" + DateTime.Now + "");
FileDownload objdwn = new FileDownload();
}
I have hosted it as a service and FileDownload class constructor will download some files from server and will copy the data into the database which will take like 10-15 minutes. So what i need to do is i should stop the timer till these fifteen minutes and the service should start again and should wait for the next minute and do the same thing. is this possible or should i just increase the timer value to greater extent
Stop() the timer at the beginning of the Elapse event and Start() the timer at the end. Also ensure your timer object does not get garbage collected.
private Timer _timer;
private DateTime _lastRun = DateTime.Now.AddDays(-1);
public SpotlessService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
_timer = new Timer(1 * 60 * 1000); // every 1 minute
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
_timer.Start();
}
public void Start()
{
OnStart(new string[0]);
}
void timer_Elapsed(object sender, EventArgs e)
{
_timer.Stop();
Util.LogError("Started at" + DateTime.Now + "");
FileDownload objdwn = new FileDownload();
_timer.Start()
}
My suggestion is to use Task to perform download and call the main method again as soon as it is finished.
public void mainMethod()
{
Thread.Sleep(60000);
doDownload();
}
public void doDownload()
{
Task.Factory.StartNew(() => {
// Background download
}).ContinueWith(task => mainMethod());
}
This will allow you to perform any additional operations in the main thread if needed while the download is in progress.
OR
You can just stop the timer and run again as soon as the download is done
void timer_Elapsed(object sender, EventArgs e)
{
_timer.Stop();
Util.LogError("Started at" + DateTime.Now + "");
FileDownload objdwn = new FileDownload();
_timer.Start();
}

Windows Service - How to make task run at several specific times?

I have a windows service running. Within it the task runs currently at 7pm every day.
What is the best way to have it run say fir example at 9.45am, 11.45am, 2pm, 3.45pm, 5pm and 5.45pm.
I know i can have scheduled task to run the function but i would like to know how to do this within my windows service. Current code below:
private Timer _timer;
private DateTime _lastRun = DateTime.Now;
private static readonly log4net.ILog log = log4net.LogManager.GetLogger
(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
protected override void OnStart(string[] args)
{
// SmartImportService.WebService.WebServiceSoapClient test = new WebService.WebServiceSoapClient();
// test.Import();
log.Info("Info - Service Started");
_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)
{
log.Info("Info - Check time");
DateTime startAt = DateTime.Today.AddHours(19);
if (_lastRun < startAt && DateTime.Now >= startAt)
{
// stop the timer
_timer.Stop();
try
{
log.Info("Info - Import");
SmartImportService.WebService.WebServiceSoapClient test = new WebService.WebServiceSoapClient();
test.Import();
}
catch (Exception ex) {
log.Error("This is my error - ", ex);
}
_lastRun = DateTime.Now;
_timer.Start();
}
}
In case you dont want to go for cron or quartz, write a function to find time interval between now and next run and reset the timer accordingly, call this function on service start and timeelapsed event. You may do something like this (code is not tested)
System.Timers.Timer _timer;
List<TimeSpan> timeToRun = new List<TimeSpan>();
public void OnStart(string[] args)
{
string timeToRunStr = "20:45;20:46;20:47;20:48;20:49";
var timeStrArray = timeToRunStr.Split(';');
CultureInfo provider = CultureInfo.InvariantCulture;
foreach (var strTime in timeStrArray)
{
timeToRun.Add(TimeSpan.ParseExact(strTime, "g", provider));
}
_timer = new System.Timers.Timer(60*100*1000);
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
ResetTimer();
}
void ResetTimer()
{
TimeSpan currentTime = DateTime.Now.TimeOfDay;
TimeSpan? nextRunTime = null;
foreach (TimeSpan runTime in timeToRun)
{
if (currentTime < runTime)
{
nextRunTime = runTime;
break;
}
}
if (!nextRunTime.HasValue)
{
nextRunTime = timeToRun[0].Add(new TimeSpan(24, 0, 0));
}
_timer.Interval = (nextRunTime.Value - currentTime).TotalMilliseconds;
_timer.Enabled = true;
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
_timer.Enabled = false;
Console.WriteLine("Hello at " + DateTime.Now.ToString());
ResetTimer();
}
Consider using Quartz.net and CronTrigger.
If u are clear abt what schedule it should run..then change time interval for timer in the timeelapsed event so that it runs according to schedule..i've never tried though
I would use a background thread and make it execute an infinite loop which does your work and sleeps for 15 minutes. It would be a lot cleaner and more simple for service code than using a timer.
See this article on MSDN.

How to use same timer for different time intervals?

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;
}
}

Categories

Resources