I have a WCF service that I host in Windows Azure. I use a Timer in this server and every 10 seconds the server needs to update something. The server is implemented in a ASP application and a WPF application.
When I initialize the Timer in the contructor like this:
public Service1()
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed += new System.Timers.ElapsedEventHandler(WCFService_Elapsed);
timer.Interval = 10000;
timer.Enabled = true;
timer.Start();
}
The timer will be started but if I restart the application the timers will run faster(because it runs a duplicate of the timer). Declare the timer above the contructor as a private property doesn't do the trick.
I already tried to use it in the OnStart method from the ServiceBase class:
private System.Timers.Timer timer;
protected override void OnStart(string[] args)
{
timer = new System.Timers.Timer();
timer.Elapsed += new System.Timers.ElapsedEventHandler(WCFService_Elapsed);
timer.Interval = 10000;
timer.Enabled = true;
timer.Start();
}
But this get never called... I also tested a static timer but that does not get started either.
What am I doing wrong?
Timer inherits IDisposable, which means Timer can and should be disposed.
I am surprised that when closing your service the timer is still running, but you should dispose at when stopping the service to fix your problem.
So in your OnStop Method you should call:
timer.Stop();
timer.Dispose();
Related
In my application I'm using two Timer, each Timer use a BackgroundWorker. Here the declaration:
DispatcherTimer timer1 = new DispatcherTimer();
DispatcherTimer timer2 = new DispatcherTimer();
BackgroundWorker worker1 = new BackgroundWorker();
BackgroundWorker worker2= new BackgroundWorker();
I using timer1 for perform an heavy method with a BackgroundWorker and timer2 for execute another BackgroundWorker that check the content of a file.
In this way I assign the event to BackgroundWorkers:
worker1.DoWork += worker_DoWork;
worker1.RunWorkerCompleted += worker_RunWorkerCompleted;
worker1.WorkerSupportsCancellation = true;
worker2.DoWork += worker_DoWork2;
worker2.RunWorkerCompleted += worker_RunWorkerCompleted2;
worker2.WorkerSupportsCancellation = true;
Now timer1 have a range of 15 minutes so the BackgroundWorker execute the heavy method each 15 minutes. And timer2 have a range of 1 second. With the timer1 all working good, but the problems are coming when I've added the timer2.
As I said before this timer allow me to start a method that read a file through the worker2, this file have a property, if this property change I need to perform some special activity. Until here no problem.
What I did is the following:
//This method is called by MainWindow
public ReadFile()
{
//before this I already assigned to timer1 the tick event and start
timer2.Tick -= new EventHandler(Event_Tick);
timer2.Tick += new EventHandler(Event_Tick);
timer2.Interval = new TimeSpan(0, 0, 1);
timer2.Start();
}
This is the Tick event associated to timer2
private void Event_Tick(object sender, EventArgs e)
{
if (!worker1.IsBusy) //I skip the reading, worker1 is busy
{
timer1.Stop(); //stop the first timer
worker2.RunWorkerAsync();
}
else
{
Console.WriteLine("worker1 is busy!");
}
}
I don't need to add here the DoWork, is just a parsing of a file, very useless for the question. When worker2 complete the task I did this:
private void worker_RunWorkerCompleted2(object sender, RunWorkerCompletedEventArgs e)
{
timer1.Start();
ReadFile();
}
How you can see I start the timer1 again, and execute again the ReadFile method. Now if timer1 has reached the interval, so 15 minutes has passed, should execute the timer1.Tick += new EventHandler(Heavy_Tick); that execute the DoWork to worker1. But the timer1 never start.
I can't figure out to this, what am I doing wrong?
Now I get it!
You want to execute worker1 every 15 minutes and worker2 every second but only when worker1 is not busy. Your problem is this here:
if (!worker1.IsBusy) //I skip the reading, worker1 is busy
{
timer1.Stop(); //stop the first timer
worker2.RunWorkerAsync();
}
and this:
public ReadFile()
{
//before this I already assigned to timer1 the tick event and start
timer2.Tick -= new EventHandler(Event_Tick);
timer2.Tick += new EventHandler(Event_Tick);
timer2.Interval = new TimeSpan(0, 0, 1);
timer2.Start();
}
Set both timer intervals and tick event handlers during startup, e.g. Form_Load()or at the beginning of Main(). Start them there too. You should not have to stop any timer at all!
By setting the interval, all you have to do is handle the Tick() event. Remove your .Start() and Stop() calls from your WorkerCompletedand Tick methods and you should do fine.
So a lot could be going on here but you should make sure that:
You timer isn't storing it's old progress and you are checking for a certain length of time before stopping. This will automatically cause the timer to stop when restarting.
The timer.stop() function is not disposing your object to an un-restart-able state.
You aren't accessing the timer variable through some pointer that is maintain a stopped value. (Unlikely but annoying when it happens)
I'd personally consider just pausing the timer and resetting the progress, instead of fully stopping it since this is causing issues.
now I have a C# application, which runs 24/7 with a timer, which elapse all 30 seconds and do anything.
I want to make this application to a windows service, to run in the background. But the service crash immediately..
My code:
public static System.Timers.Timer _timer = new System.Timers.Timer();
static void Main(string[] args)
{
_timer.Interval = 30000;
_timer.Elapsed += timerCallback;
_timer.AutoReset = true;
_timer.Start();
}
public static void timerCallback(Object sender, System.Timers.ElapsedEventArgs e)
{
// Do anything..
}
And the error:
Windows could not start the Application service on Local Computer.
Error 1053: The service did not respond to the start or control request in a timely fashion
In the windows event viewer this message occured:
A timeout was reached (30000 milliseconds) while waiting for the Application service to connect.
But the error appear faster than 30 seconds?!
Any solutions to run the service??
Thanks
Michael
You could use a Timer to execute the logic periodically within windows service,
protected override void OnStart(string[] args)
{
base.OnStart(args);
Timer timer = new Timer();
timer.Interval = 30*1000;
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
timer.Start();
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
//put logic here that needs to be executed for every 30sec
}
I wonder how i can force my window service to restart or stop if it's running for already about 30 mins.
it's like:
if(service.runs == 30 mins){
service.stop()
or
service.restart()
}
by the way, I am using C# on this. And I am using a Thread here.
This is how my OnStart looks like:
Thread myThread;
protected override void OnStart(string[] args){
myThread = new Thread(new ThreadStart(this.myThreadFunction));
myThreadFunction.Start();
}
Please help.
Thanks
You need to run timer on service start. And set its elapsed event to 30 mins. If it is elapsed then you can apply your above check of stopping it. You also need to Reset your timer when ever the service is stopped/restarted.
//somewhere in your class
System.Timer.Timer tmr = new System.Timers.Timer();
//on construct or start event
tmr.Interval = 1800000; //30 minutes = 60*1000*30
tmr.Elapsed -= new ElapsedEventHandler(OnTimedEvent);
tmr.Elapsed += new ElapsedEventHandler(OnTimedEvent);
tmr.Start();
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
tmr.Stop();
ServiceController service = new ServiceController(yourserviceName);
service.Stop();
// service.Start() uncomment this line if your want to restart
}
protected override void OnStop()
{
}
I want to show timer on UI such that when aplication star executing timer starts with 00:00:00 and when it completed its execution timer stops. Timer should show timing per second while running.
You can use the System.Windows.Forms.Timer, which is created for scenarios like yours. You can read more about in MSDN.
You should use the following code snippet as sample:
Timer timer = new Timer();
timer.Interval = 1000;
timer.Tick += new System.EventHandler(timer_Tick);
timer.Start();
private void timer_Tick(object sender, System.EventArgs e)
{
this.Text = string.Format("{0:hh:MM:ss}", DateTime.Now);
}
Notice that you should dispose the Timer when you do not needed.
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.