I have created a windows service on VS.net C#
In the OnStart event I start a timer.
In side the timer I call a function called DO()
the process of the DO() function is very long ( takes more than hour)
The process suppose to go this way
Start Then call the time immediately but due to the timer interval need to wait another day
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart.");
try
{
Timer timer = new Timer();
timer.Interval = 1000 * 60 *60 * 24;
timer.Elapsed += new ElapsedEventHandler(this.OnTimer);
timer.Start();
DO();
}
catch (Exception ex)
{
eventLog1.WriteEntry("ERROR (OnStart) : " + ex.ToString());
}
}
public void OnTimer(object sender, ElapsedEventArgs args)
{
DO();
}
private void DO()
{
// Some process takes an hour
}
When the service starts it stays an hour in "Starting"
Is there a way I can start my service DO() function immediatly once the service started but not from the OnStart event?
Presuming you left nothing out of your example, your timer elapsed method will run on the ThreadPool.
So I would change this line in OnStart
DO();
...with this line:
ThreadPool.QueueUserWorkItem(x => Do());
It has the same net effect of what would happen if the timer fired immediately and, more importantly, will not block on that line.
Related
I have a Timer (System.Timers.Timer) that triggers every 100ms.
I subscribe an Event Handler to the Timer and it works just fine:
public override void TimerEvent(object source, ElapsedEventArgs e)
{
lock (timerlock)
{
Timer.Stop();
...
Timer.Start();
}
}
I use the timerlock, so when I unsubscribe from the timer I can be sure I am not in the middle of my TimerEvent Method.
So then when I want to unsubscribe from the Timer I do this:
lock (timerlock)
{
Timer.Elapsed -= TimerEvent;
}
try
{
DoSomethingThatTakesUpToAMinute();
}
catch (Exception ex)
{
MessageBox.Show("...");
}
finally
{
Timer.Elapsed += TimerEvent;
}
But when I subscribe to the Timer again in the finally block, my program takes up to 15 seconds until the next timer Event is registered even tho the finally was already executed. Note that what I do between unsubsribing and resubscribing to the timer can take up to a Minute.
I can see in the console that there are About 5 Threads that end with error Code 0 after the finally block and once they all ended my TimerEvents are Triggered again.
Any ideas?
I have a method that executes in about 10 minutes. And it goes well just by itself. I need to start this method every hour using windows service (this is obligatory). So I've written my service by some examples (just one invoke for start):
partial class ServiceWSDRun : ServiceBase
{
protected override void OnStart(string[] args)
{
Thread t = new Thread(WebServiceDownload.MainProgram.Execute);
t.Start();
}
}
Now when I install it, it launches my method in a new thread but this thread seem to end with the OnStart() - it actually logs some info from the beginning of me method. Why does it stop and what should I do?
And I'm thinking in the end I should have something like this:
partial class ServiceWSDRun : ServiceBase
{
System.Timers.Timer timer = null;
protected override void OnStart(string[] args)
{
Thread t = new Thread(WebServiceDownload.MainProgram.Execute);
t.Start();
timer = new System.Timers.Timer();
timer.Interval = 60 * 60 * 1000; // 1 hour
timer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimer);
timer.Enabled = true;
}
public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
WebServiceDownload.MainProgram.Execute();
}
protected override void OnStop()
{
timer.Enabled = false;
}
}
How do I make it work? And keep in mind that method takes ~10 mins to execute.
You should use System.Threading.Timer instead of System.Timers.Timer.
Here is the reference for this:
https://msdn.microsoft.com/en-us/library/system.threading.timer(v=vs.110).aspx
Also, another thread about the same topic:
System.Timers.Timer vs System.Threading.Timer
You should lock the execution, avoiding the second execution before the first one finishes.
I have a windows service, this service every x second or minute, should perform a task. I have write this service, install it on my SO (Windows 7), so it work for three hours about, then the state of service is "Running" but it has ceased to perform the task. I think, the timer is in crash.
This is a code:
public Service1()
{
InitializeComponent();
if (!System.Diagnostics.EventLog.SourceExists("AutomaticallyRunScript"))
{
System.Diagnostics.EventLog.CreateEventSource(
"AutomaticRunScript", "LoggerAutomaticRunScript");
}
log.Info("preparazione file di config in corso...");
//set parameter from config File
setParameterFromAppConfig();
// get today's date at hours:minutes
DateTime tenAM = DateTime.Today.AddHours(hours);
tenAM = tenAM.AddMinutes(minutes);
int timeToFirstExecution = 0;
// if hours:minutes has passed, get tomorrow at hours:minutes
if (DateTime.Now > tenAM)
tenAM = tenAM.AddDays(1);//add 1 day of data
// calculate the number of milliseconds in hoursFrequency, minutesFrequency, secondsFrequency time.
int timeBetweenCalls = (int)new TimeSpan(hoursFrequency,
minutesFrequency, secondsFrequency).TotalMilliseconds;
// if hours:minutes has passed, get tomorrow at hours:minutes
//only if the frequency of the run script is every day
if (DateTime.Now > tenAM && hoursFrequency == 24)
{
tenAM = tenAM.AddDays(1);//add 1 day of data
// calculate milliseconds until the next hours:minutes .
timeToFirstExecution = (int)tenAM.Subtract(DateTime.Now).TotalMilliseconds;
}
else
{
timeToFirstExecution = (int)DateTime.Now.AddMilliseconds(timeBetweenCalls).Subtract(DateTime.Now).TotalMilliseconds;
}
// set the method to execute when the timer executes.
TimerCallback methodToExecute = ProcessFile;
// start the timer. The timer will execute "ProcessFile" when the number of seconds between now and
// the next hours:minutes elapse. After that, it will execute every 24 hours.
System.Threading.Timer timer = new System.Threading.Timer(methodToExecute, null, timeToFirstExecution, timeBetweenCalls);
// Block the main thread forever. The timer will continue to execute.
//Thread.Sleep(Timeout.Infinite);
}
protected override void OnStart(string[] args)
{
//
}
protected override void OnStop(string[] args)
{
//
}
public void ProcessFile(object obj)
{
try
{
// do your processing here.
String percorsoFiles = ConfigurationManager.AppSettings["NameFileBat"];
string[] percorsoFile = percorsoFiles.Split(';');
foreach (string filebatch in percorsoFile)
{
//log.Info(": EXECUTE BATCH FILE " + filebatch + " NOW");
EventLog.WriteEntry("EXECUTE BATCH FILE " + filebatch + " NOW", EventLogEntryType.Information);
System.Diagnostics.Process.Start(filebatch);
//System.Threading.Thread.Sleep(elapsedTimeBetween2BatchFile);
}
EventLog.WriteEntry("***FINISHED***", EventLogEntryType.Information);
//log.Info("***FINISHED***");
}
catch (Exception e)
{
EventLog.WriteEntry("error, see log file ", EventLogEntryType.Error);
log.Error("errore: " + e);
}
}
I have see the log file and there isn't an error log
Ok, where do I start...
First of all, put as little code as possible into the constructor. All code required to initialize the service should be in OnStart, all code required to stop the service (i.e. code to stop the timer) should be in OnStop. That's the first thing.
Then it is good practice to stop a timer while the timer event is executing and to restart it in a finally block at the end of the timer event.
Third I recommend not to use System.Threading.Timer but System.Timers.Timer which is easier to handle and allows for "one shot" timers, which force you to restart the timer in code. Less things can go wrong here.
Also, do never ever create timers as local variables! They may get garbage collected any time after the method is out of focus.
And why is everybody using ConfigurationManager.AppSettings when it is so much easier and less error-prone to write Properties.Settings.Default.NameFileBat?
Short example of how to use System.Timers.Timer in service:
private System.Timers.Timer myTimer;
protected override void OnStart(string[] args)
{
myTimer = new Timer(5000); // Every 5 seconds
myTimer.AutoReset = false; // Only 1 event!!
myTimer.Elapsed += TimerElapsed; // Event handler
myTimer.Start(); // Start the timer
}
protected override void OnStop()
{
myTimer.Stop();
myTimer = null;
}
privated void TimerElapsed(object source, ElapsedEventArgs e)
{
try
{
// Do stuff
}
finally
{
// Restart if timer variable is not null
if (myTimer != null)
myTimer.Start();
}
}
I have a C# program that is constantly checking for new additions to an online DB. I have this code to have it check every 10 seconds
static void Main(string[] args)
{
boolean run = true;
while (run)
{
DBConnect Db = new DBConnect();
// do amazing awesome mind blowing cool stuff
Db.closeConnection();
// wait for 10 seconds
int wait = 10 * 1000;
System.Threading.Thread.Sleep(wait);
}
}
i have error reporting that posts to the DB and if a major error occurs the program shuts down. Outside of the specific errors within my function, is this method secure and efficient?
You should rewrite your program as a windows service, that way you do not need to rely on a user to be logged for your program to run.
If you do go with the service route, I would swap out the infinite loop for a timer.
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
int wait = 10 * 1000;
timer = new Timer(wait);
timer.Elapsed += timer_Elapsed;
// We don't want the timer to start ticking again till we tell it to.
timer.AutoReset = false;
}
private System.Timers.Timer timer;
protected override void OnStart(string[] args)
{
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
DBConnect Db = new DBConnect())
try
{
// do amazing awesome mind blowing cool stuff
}
finally
{
Db.closeConnection(); //We put this in a finally block so it will still happen, even if an exception is thrown.
}
timer.Start();
}
catch(SomeNonCriticalException ex)
{
MyExecptionLogger.Log(ex, Level.Waring); //Log the exception so you know what went wrong
timer.Start(); //Start the timer for the next loop
}
catch(Exception ex)
{
MyExecptionLogger.Log(ex, Level.Critical); //Log the exception so you know what went wrong
this.Stop(); //Stop the service
}
}
protected override void OnStop()
{
timer.Stop();
}
}
Write it as a console program without the wait and set up a scheduled task to run it periodically. You want to run it every 10 seconds? Every minute? Just change the scheduled task.
You can use the Task Scheduler GUI, or the schtasks command line tool.
See Programs are not cats.
I would setup a windows service and use SqlDependency http://msdn.microsoft.com/en-CA/library/a52dhwx7(v=vs.80).aspx. That way when a change (which you specify) occurs in the database, it will trigger the OnChange event which you specify to do whatever it is you need to do. See the link for implementation details.
I have a Service that hits a database every 10 sec and gets the data if there is any. The thing is that processing this data can take up to 30 sec. If I use a Timer with 10 sec interval the service will get the same data twice.
The effect i´m trying to achieve(Just for visualization):
while(true)
{
if(Getnrofrows() > 0)
do stuff
else
sleep for 10 sec
}
Ppl saying Thread.Sleep is a bad idea in production services, how do I do this with timers?
/mike
Did you try to set Timer property auto reset to false, and enabling timer again when process of refreshing data is over
using System;
public class PortChat
{
public static System.Timers.Timer _timer;
public static void Main()
{
_timer = new System.Timers.Timer();
_timer.AutoReset = false;
_timer.Interval = 100;
_timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
_timer.Enabled = true;
Console.ReadKey();
}
static void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//Do database refresh
_timer.Enabled = true;
}
}
I don't see any problems with using Sleep at all other than you might end up with ugly code.
To answer your question:
public class MyTest
{
System.Threading.Timer _timer;
public MyTest()
{
_timer = new Timer(WorkMethod, 15000, 15000);
}
public void WorkMethod()
{
_timer.Change(Timeout.Infinite, Timeout.Infinite); // suspend timer
// do work
_timer.Change(15000, 15000); //resume
}
}
There is nothing wrong with this approach. A sleeping thread does not consume any CPU cycles.
If you need to do something exactly every X seconds, a timer is the way to go. If, on the other hand, you want to pause for X seconds, then Thread.Sleep is appropriate.
Thread.Sleep is not bad in itself in a service, just that you need to be responsive to service commands, so your worker thread should not go to sleep for an hour, but rather needs to sleep for short periods of time and then wake up and listen if the service controller part of the service is telling it to stop for some reason.
You want to make it so that if the admin tells your service to stop, it'll stop quickly enough so that it won't get any timeout messages where the admin can't be sure that your service is stopped and it's safe to reboot the machine or similar.