I am trying to complete my college assignment, which asks to create a time driven event. A report should be automatically emailed to a responsible person twice everyday. I need to get the times from a database which I can do quite easily. For now, I have created a timer like this:
private static void getDate()
{
DateTime now = DateTime.Now;
DateTime alarm = new DateTime(2015, 10, 27, 19, 23, 0);
TimeSpan diff = alarm - now;
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
// Set the Interval to the difference in time from now to your alarm.
if (diff.TotalMilliseconds > 0)
{
aTimer.Interval = diff.TotalMilliseconds;
aTimer.Enabled = true;
}
else
{
aTimer.Enabled = false;
aTimer.AutoReset = true;
aTimer.Dispose();
}
}
When the form is initialized, the getDate() function is executed to start the timer. When the timer hits the specific time, I run this code:
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine("Hello World!");
XslCompiledTransform transformer = new XslCompiledTransform();
transformer.Load("report.xsl");
transformer.Transform("Report.xml", "Report.html");
string html = File.ReadAllText("Report.html");
SendMail(html);
}
After the e-mail is sent to a person, I run the getDate() function again to update the time. However, the timer doesn't seem to stop. It defaults to Interval of 100.00 and runs the OnTimedEvent() is executed. I am not sure what changes I should make. So basically the timer needs to run off two different times during the day. When the report is sent both times, it should default to the earliest time the following day (if that makes any sense).
Thank you for any suggestions.
Timer has a property of AutoReset, set this to false to disable it automatically restarting after the Elapsed event.
e.g.:
System.Timers.Timer aTimer = new System.Timers.Timer
{
AutoReset = false
};
When you call getDate() again it is creating a second (new) instance of Timer. Your first Timer is still ticking. To fix this, you need to move the Timer instantiation out of the getDate() method. Move it to the constructor
//Move this to the constructor
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
Related
I have simple timer:
private System.Timers.Timer _timer;
public Ctor()
{
_timer = new System.Timers.Timer(timeout);
_timer.Elapsed += Timer_Elapsed;
_timer.Start();
}
How to make that timer rise Elapsed event after timeout time expired?
It is for the first elapsed event, of course.
A Timer does exactly what you want , it raises the event after the specified interval elapses. If you don't want it to be recurring (Runs once only), then set the AutoResetProperty:
public Ctor()
{
_timer = new System.Timers.Timer(timeout);
_timer.AutoReset = false;
_timer.Elapsed += Timer_Elapsed;
_timer.Start();
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
// your code here runs after the timeout elapsed
}
I think you're asking for a timer to be started after an initial delay? If that's the case then consider using a System.Threading.Timers.Timer instead, as follows:
int initialDelay = 5000; // five seconds
int timerPeriod = 1000; // one second
var timer = new Timer(_ => MethodToCallWhenExpired(), null, initialDelay, timerPeriod);
Alternatively you can use Timeout.Infinite and then call the Change() method to alter the Timer behaviour after creation.
Sorry if that's not what you were asking though! :)
My android app uses a timer in a certain place.
I get an exception when the time exceeds an hour (3600000), it says the period is too large.
myTime = "3600000";
TempTimer = new System.Threading.Timer ((o) => {
ContentCheck(); // function call/ Void call <----------
}, null, 0, Int64.Parse(myTime) );
I've tried int.parse() already, so tried int64 (Hence it being in code..)
Is there a timer that can do an hour AND longer? Or perhaps and alternative method to get the same results as a timer?
Timer timer = new Timer();
timer.Interval = 3600000;
timer.AutoReset = false;
timer.Start ();
timer.Elapsed+= Timer_Elapsed;
void Timer_Elapsed (object sender, ElapsedEventArgs e)
{
Console.WriteLine("Timer has gone off");
}
Here the interval property of timer instance is of type Double. So that can store really large values. So this should work for you.
I would to make a timer which behaviour is like this:
if processing time of task/job is less than timer interval, start timer in (timer.interval - processing time job/job)
if processing time of job/task is more than timer interval, start next job/task immediatly
Code below works but I would like to know why in the ElapsedEventHandler method job/task must be first done and then we can set new timer interval. Elapsed event of System.Timers.Timer is raised when interval has elapsed. With the option AutoReset = false we set that the Timer raises the Elapsed event only once, after the first Interval has elapsed. We have to then manually call Timer.Start() to start it again.
using System;
using System.Timers;
namespace TestTimer
{
class Program
{
private static Timer t;
private static double intervalMiliseconds;
static void Main(string[] args)
{
intervalMiliseconds = 5000; // 5 seconds
t = new Timer();
t.Interval = intervalMiliseconds;
t.AutoReset = false;
t.Elapsed += new ElapsedEventHandler(OnTimedEvent);
t.Start();
log("Timer started at " + DateTime.Now.ToString());
log("Interval is: " + defaultIntervalMiliseconds);
Console.ReadKey();
}
private static void log(string text)
{
Console.WriteLine(text + "\n");
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// if t.Interval is set here thread just kills the job if it
// runs longer than interval
t.Interval = intervalMiliseconds;
log("ElapsedEvent triggered at " + DateTime.Now.ToString());
// job
DateTime startTime = DateTime.Now;
log("job started" );
System.Threading.Thread.Sleep(8000); // 8 sec
log("job ended" );
TimeSpan jobTime = DateTime.Now.Subtract(startTime);
log("job took " + jobTime.TotalSeconds + " seconds");
// if we set t.Interval here it works so first the job
// must be done and than we can set timer interval ? why ?
//t.Interval = intervalMiliseconds;
if (jobTime.TotalMilliseconds < t.Interval)
{
t.Interval = t.Interval - jobTime.TotalMilliseconds;
log("Job ended Earlier starting Event in: " + t.Interval);
}
else
{
t.Interval = 100;
log("Job overpass interval. Current time: " +
DateTime.Now.ToString());
}
t.AutoReset = false;
t.Start();
}
}
}
Result of this:
If we comment t.Interval at the start of method OnTimedEvent and uncomment t.Interval after the job has done everything works. Result of this:
Why we can not set timer interval at the start of method OnTimedEvent. If we do if the task/job runs longer than the timer interval, thread just kills the job. I would really appreciate if anyone has some ideas? Does this have to do with synhronization of thread with main thread (which timer runs)? When we call method OnTimedEvent the timer will not call that method again because it has AutoReset = false, what difference does it make where we set timer properties?
t.Interval = intervalMiliseconds;
That's indeed the troublemaker. It is pretty unintuitive behavior, one that the MSDN article for Timer.Interval specifically warns about in a Note:
If Enabled and AutoReset are both set to false, and the timer has previously been enabled, setting the Interval property causes the Elapsed event to be raised once, as if the Enabled property had been set to true. To set the interval without raising the event, you can temporarily set the AutoReset property to true.
It's a fairly silly hack but does work. Just delaying assigning the value is certainly the better way to do it. Doing it early doesn't buy you anything, other than trouble, the timer isn't going tick anyway since you've got AutoReset = false.
System.Threading.Timer is the better timer class with many fewer quirks. It for one doesn't swallow exceptions without any diagnostic in the callback method. Which your code is quite sensitive to, the timer will just stop ticking since the exception bypasses the t.Start() call and you'll have no idea why. Strongly recommended.
!! No and never Timer kill task/job if it runs longer than timer interval !!
if processing time of task/job is less than timer interval,
after timer interval/span.
if processing time of job/task is more than timer interval,
start next job/task after timer interval/span into a new Thread.
so for minimizing idle time you should keep timer interval small.
In System.Timers.Timer class internally already Threading Implemented. so don`t need to implements threading.
How do I get System.Timers.Timer to trigger Elapsed events every 15 mins in sync with the system clock? In other words, I want it to trigger exactly at xx:00, xx:15, xx:30, xx:45 (where xx means any hour)
You could let it elapse every second and check whether the current time is 00, 15, 30 or 45 and only then forward the event.
A first idea would be:
private static System.Timers.Timer aTimer;
private static System.DateTime _last;
public static void Main()
{
aTimer = new System.Timers.Timer(10000);
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 1000;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program.");
Console.ReadLine();
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
DateTime time =
new DateTime( 1,1,1, DateTime.Now.Hours, DateTime.Now.Minute );
if( time.Minute==0 ||time.Minute==15 || time.Minute==30 || time.Minute==45 )
{
// Avoid multiple notifications for the same quarter.
if ( _last==DateTime.MinValue || _last!=time )
{
_last = time;
// Do further processing.
doProcessing();
}
}
}
(Example based on this MSDN documentation)
When starting the program, or changing the event times that will be triggered, load the event times into memory (to keep from reading this data from the hard drive every second.) Then set up a timer to fire every 1 second. A timer set to fire every 1 second is very little overhead on the processor. Set one up and open task manager and you will not even notice the processor running any more than before the timer was running. Then put a check in the timer event to check if it is time to fire an event.
use Quartz.net. Then you can use regex to define the interval.
I have a windows service written in C# that executes a method correctly. I added a timer to schedule the method execution and it doesn't seem to fire the ElapsedEventHandler event.
System.Timers.Timer timer = new System.Timers.Timer();
public LabelService()
{
InitializeComponent();
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
}
public void SetTimer()
{
DateTime nextRunTime = GetNextRunTime();
var ts = nextRunTime - DateTime.Now;
timer.Interval = ts.TotalMilliseconds;
timer.AutoReset = false;
timer.Start();
}
void timer_Elapsed(object source, ElapsedEventArgs e)
{
// ** never gets here **
timer.Stop();
// run some code
SetTimer();
}
I can run and hit a breakpoint at timer.Start(); so I know that's being done, but it never falls into the timer_Elapsed method. (For testing I change ts.TotalMilliseconds to 1000) Any ideas?
"If Enabled is set to true and AutoReset is set to false, the Timer raises the Elapsed event only once, the first time the interval elapses. When Enabled is true and AutoReset is true, the Timer continues to raise the Elapsed event on the specified interval."
So I think you gotta set
timer.AutoReset = true;
I know this is old, but for anyone else with the same problem I was able to work around this by using;
public void StartTimer()
{
_timer.Interval = _pollingIntervalMilliseconds;
_timer.Enabled = true;
_timer.AutoReset = false; // We must manually restart the timer when we have finished processing
_timer.Elapsed += CheckForUpdates;
_timer.Start();
if (Environment.UserInteractive)
{
Console.WriteLine("System now running, press a key to Stop");
Console.ReadKey();
}
}
private void CheckForUpdates(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Checking For Update");
DoSomethingSlow();
_timer.Start(); // restarts the timer to hit this method again after the next interval
}
It will keep hitting the Elapsed Event until you hit a key to exit
From comments on the question you say you are calling it like this:
#if (!DEBUG)
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new LabelLoader() };
ServiceBase.Run(ServicesToRun);
#else
LabelLoader ll = new LabelLoader();
ll.Start();
#endif
If you are in debug mode that means your main method is this:
LabelLoader ll = new LabelLoader();
ll.Start();
This means that once it has run these two lines the program finishes running and presumably exits. It doesn't matter what your timer is up to, the program has quit and thus your timer never fires.
I'd advise testing your ll with a better harness. Personally I use a winform type interface and just have a start button to mimic the service start (which will then have your code in the button click). Once I think I have that code running as I want I then test it in a service environment.