Windows Service with timer 25 seconds later - c#

I have this simple windows service that is part of a browser game. What it does is check against database and if needed updates some rows. These actions takes about .5 to 1 second.
The data it reads is a date which tells if an item should be updated.
It works perfectly, however it is always around 25 seconds late. If I add an item to the queue, and that item is completed at 15:00:00, the service will update it at 15:00:25ish.
I've tried using threading.timer, a single thread and timers.timer and all works in the same way. I've also tried stopping the timer while the elapsed was running, although it takes less than a second so it should not be a problem.
I've also tried to attach the service to a debugger, and the same thing happens UNLESS I put a breakpoint. Then it happens as soon as it hits the breakpoint and i press f5 to continue.
Can anyone shed some light as to why the service seems to be behind? And a possible fix.
I was thinking I ran out of thread but I have a good 1000 left, so I'm kinda blank.
Please ask if you need more details, so I can provide.
I'm using .net 4.0 / C#
Threading.Thread
public partial class Service : ServiceBase
{
Thread thread;
public Service()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
thread = new Thread(DoWork);
thread.Start();
}
private static void DoWork()
{
while (true)
{
//finish workingqueueitems
WorkingQueue.ProcessFinishedItems();
Thread.Sleep(1000);
}
}
protected override void OnStop()
{
thread.Abort();
}
}
Timers.Timer
public partial class Service : ServiceBase
{
System.Timers.Timer workingQueueTimer;
public Service()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
workingQueueTimer = new System.Timers.Timer();
workingQueueTimer.Elapsed += new ElapsedEventHandler(workingQueueTimer_Elapsed);
workingQueueTimer.Interval = 1000;
workingQueueTimer.Enabled = true;
}
void workingQueueTimer_Elapsed(object sender, ElapsedEventArgs e)
{
workingQueueTimer.Enabled = false;
DoWork();
workingQueueTimer.Enabled = true;
}
private static void DoWork()
{
//finish workingqueueitems
WorkingQueue.ProcessFinishedItems();
}
protected override void OnStop()
{
workingQueueTimer.Stop();
workingQueueTimer.Dispose();
}
}

The problem could be due to:
your DoWork() method takes 25 sec to complete
You are seeing the db data cached in someway or a transaction is delaying it
your method WorkingQueue.ProcessFinishedItems() is taking the wrong rows to update
if your service and db are in separeted machine they have a different time clock of 25 sec

Related

Multiple timers in windows service not working properly

I have 2 different timers in my windows service each of which I am running at intervals of every 5 seconds, however they are both not being run at the same time.
My logs simplified logs look like the following
11:49:00 : Timer1
11:49:05 : Timer1
11:49:10 : Timer1
11:49:15 : Timer1
11:49:20 : Timer1
11:49:25 : Timer1
11:49:30 : Timer1
11:49:35 : Timer1
11:49:48 : Timer2
11:49:53 : Timer2
11:49:58 : Timer2
This continues with just one being activated for the correct period of 5 seconds then the other. I want both of them to be run.
I understand you will ask "why not put them in the same timer?" but i will be adding multiple more timers and the timing of these events are likely to change so I'd really like to fix this problem just now.
Here is my code,
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
//Read or Create xml file to get necessary settings
SerializeIformBuilder();
//Checks for any user changes that may have occurred
var manageUsers = new App.BLL.ManageUsers();
System.Timers.Timer CreateNewUserTimer = new System.Timers.Timer();
System.Timers.Timer PasswordUpdateTimer = new System.Timers.Timer();
//Create Timer interval events
CreateNewUserTimer.Elapsed += new System.Timers.ElapsedEventHandler(manageUsers.TimedEvent_CreateNewUsers);
CreateNewUserTimer.Interval = 5000; //Once every 5 seconds
CreateNewUserTimer.Enabled = true;
PasswordUpdateTimer.Elapsed += new System.Timers.ElapsedEventHandler(manageUsers.TimedEvent_PasswordUpdate);
PasswordUpdateTimer.Interval = 5000; //Once every 5 seconds
PasswordUpdateTimer.Enabled = true;
}
The Interval of Timer is not actually guaranteed, same as you can't count on Thread.Sleep(5000) sleeping exactly 5 seconds.
If both delegates need to be executed at the exact same time, you'll need to implement your own special timer, e.g. one that holds multple delegates and knows their execution intervals.
simplified:
public class Job
{
public int ExecutionInterval { get; set; }
public Action Action { get; set; }
}
public class TimedExecutionHandler
{
private List<Job> jobs = new List<Job>();
public void Start()
{
// start internal thread on loop
}
public void Stop()
{
// interrupt thread
}
public void RegisterJob(Job job)
{
// store job
}
private void Loop()
{
int count = 0;
while (true)
{
Thread.Sleep(1000);
count++;
foreach (Job job in this.jobs)
{
if (count % job.ExecutionInterval == 0)
{
job.Action();
}
}
}
}
}
I have also had this issue, if your timers are running multiple things or doing complex calculations sometimes your program can run out of space, designated ram or overall just get too big(in terms of size and running lines of code). Just keep this in mind next time your using multiple timers or performing complicated tasks- your application had a designated amount of memory and timers use the memory up like crazy. Thanks! I hope that helped!

Windows Service Tick ElapsedEventArgs is never called

I tried to deploy one service which works great in local to the production server. But on this server, the ElapsedEventHandler seems to never call my method Tick()
I have read other similar threads as
First Windows Service - timer seems not to tick
or
Timer tick event is not called in windows service
but i couldn't have any answer to my problem :/
I also tried to use _timer.Enabled=1 instead of _timer.Start (no incidence normally but still tried) and also tried to reinstall service a couple of times.
I use the Timer from Class System.Timers.
here is my code :
static void Main()
{
var servicesToRun = new ServiceBase[]
{
new SynchronizeEvents()
};
#if DEBUG
servicesToRun.LoadServices();
#else
ServiceBase.Run(servicesToRun);
#endif
}
and
public partial class SynchronizeEvents : ServiceBase
{
private readonly Logger _logger = LogManager.GetCurrentClassLogger();//Nlog
private Timer _timer;//From Class System.Timers
private readonly DbSetName _db = new DbSetName ();
private static readonly Dictionary<Employee, otherStuff> Subscriptions = new Dictionary<Employee, otherStuff>();
public SynchronizeEvents()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
_logger.Trace("Service Start");
_timer = new Timer(5000) { AutoReset = false };//Same problem without AutoReset = false
_timer.Elapsed += Tick;
_timer.Start();
_logger.Trace("End OnStart");
}
protected override void OnShutdown()
{
_logger.Trace("OnShutdown");
_timer.Stop();
base.OnShutdown();
}
protected void Tick(object sender, ElapsedEventArgs elapsedEventArgs)
{
_logger.Trace("Tick");
_timer.Stop();
Compute();
_timer.Start();
}
protected override void OnStop()
{
_logger.Trace("OnStop");
}
Everything works great while on DebugMode and also on local computer in Release mode, but when i install it on production server the only logs i got are :
2014-09-08 16:35:57.1929 TRACE Service Start
2014-09-08 16:35:57.2085 TRACE End OnStart
i also got this when i stop the service...
2014-09-08 16:40:52.4072 TRACE End OnStop
Actually i got to apologize to Steve Wellens, he was right to ask about what Compute do.
The problem was related to Compute().
It had some code which required a DLL which was missing.
I don't know why _logger.Trace("Tick"); wasn't called and no Exception was triggered :/
I had to comment my program line per line to find out where the problem came from...

Fail to Keep windows service with Timer alive

I have a windows service that I made for MY server...
I need to check every minute if there is some new info in my SQL Database.
So I made a windows service that create a Timer with interval of 1 minute.
But The windows service set the timer and ending the run.
It's goes like this:
Starting Service
Setting Timer with interval
Finishing and exiting Service <-- I want to keep it alive
As you can see the Service exit and I want the Windows service to run every minute without stopping....
I can see in the Event Viewer that there are the "Service started successfully." And the "Service stopped successfully."
What should I do?
P.S : I thought Timer should work with out exit... or may I wrong?
CODE:
Windows service:
static void Main(string[] args)
{
try
{
Utils.SetConfigFile();
var ServiceToRun = new TaoTimer();
ServiceToRun.Start();
}
catch (Exception ex)
{
EventLog.WriteEntry("Application", ex.ToString(), EventLogEntryType.Error);
}
}
TaoTimer:
public partial class TaoTimer : ServiceBase
{
List<TimerModel> timerList;
public TaoTimer()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
EventLog.WriteEntry("Started");
}
public void SetTimer(TimerModel timerModel)
{
int minute = 1000 * 60;
try
{
AlertTimer at = new AlertTimer(timerModel, minute);
at.Start();
}
catch
{
}
}
protected override void OnStop()
{
EventLog.WriteEntry("Stopped");
}
protected override void OnPause()
{
EventLog.WriteEntry("Paused");
}
protected override void OnContinue()
{
EventLog.WriteEntry("Continuing");
}
protected override void OnShutdown()
{
EventLog.WriteEntry("ShutDowned");
}
public void Start()
{
SetTimerList();
}
protected void SetTimerList()//Read Config from xml and start the timer
{
XElement root = XElement.Load(#"C:\TaoTimer\Data.xml");
timerList = new List<TimerModel>(from d in root.Descendants("Timer")
select new TimerModel(
d.Element("Id").Value.ToString(),
d.Element("Name").Value.ToString(),
d.Element("InterVal").Value.ToString(),
d.Element("TimeFormat").Value.ToString(),
d.Element("Day").Value.ToString(),
d.Element("TimeStamp").Value.ToString()));
timerList.ForEach(i => SetTimer(i));
}
}
AlertTimer:
public class AlertTimer
{
static System.Timers.Timer aTimer = new System.Timers.Timer();
public AlertTimer(TimerModel timerModel, int milliseconds)
{
aTimer.Elapsed += new ElapsedEventHandler((sender, e) => OnTimedEvent(sender, e, timerModel));
aTimer.Interval = milliseconds;
}
public void Start()
{
aTimer.Enabled = true;
}
public static void OnTimedEvent(object source, ElapsedEventArgs e, TimerModel timerModel)
{
getAbsenceContacts.Start();<-- NEVER GETS HERE....
}
}
You're not actually starting your service. You're calling a method named Start, which is not part of the Windows Service class hierarchy it's just a method you've defined. Your method runs and finishes, so the service exits.
Try this:
static void Main(string[] args)
{
try
{
Utils.SetConfigFile();
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new TaoTimer()
};
ServiceBase.Run(ServicesToRun);
}
catch (Exception ex)
{
EventLog.WriteEntry("Application", ex.ToString(), EventLogEntryType.Error);
}
}
public partial class TaoTimer : ServiceBase
{
...
protected override void OnStart(string[] args)
{
SetTimerList();
EventLog.WriteEntry("Started");
}
....
}
and remove the Start method from TaoTimer entirely.
You need to store your AlertTimer instances in something that will last the lifetime of the service (e.g. in a List<AlertTimer> declared as a field inside TaoTimer.
It's only really alluded to in the documentation for Timer that timer's, in and of themselves, don't prevent themselves from being garbage collected. The example says:
// Normally, the timer is declared at the class level,
// so that it stays in scope as long as it is needed.
// If the timer is declared in a long-running method,
// KeepAlive must be used to prevent the JIT compiler
// from allowing aggressive garbage collection to occur
// before the method ends. You can experiment with this
// by commenting out the class-level declaration and
// uncommenting the declaration below; then uncomment
// the GC.KeepAlive(aTimer) at the end of the method.
//System.Timers.Timer aTimer;
Now, whilst your timer's are declared at the class level inside of your AlertTimer class, there's nothing to stop the AlertTimer instances, themselves, from being collected. And the GC only keeps things alive that are transitively reachable. Once the AlertTimer instances are collectible, so are your Timer objects.

How to invoke a control within a class

I have a windows form with a button.
I click the button and it starts a method in a separate class. I start this method in a separate thread.
When this class.method finishes it raises an event back to the windows form class.
When this happens I start another method in that separate class that tells a system.windows.form timer (declared in that class) to be enabled and thus start processing.
But the timer does not start (I did put a break point inside the 'tick' event).
I am assuming that it is because I declared the timer outside of the calling thread right at the start of my code.
Normally, I would use this to invoke a method on the same thread...
this.invoke(mydelegatename, any pars);
But, 'this' cannot be called with an class because unassumingly it is related to the UI thread.
I know this all looks bad architecture and I can easily solve this problem by moving the timer to the UI thread (windows form class).
But, I have forgotten how I did this many years ago and it really is an attempt to encapsulate my code.
Can anyone enlighten me pls?
Thanks
The Code:
[windows class]
_webSync = new WebSync(Shared.ClientID);
_webSync.evBeginSync += new WebSync.delBeginSync(_webSync_evBeginSync);
Thread _thSync = new Thread(_webSync.PreConnect);
_thSync.Start();
private void _webSync_evBeginSync()
{
_webSync.Connect();
}
[WebSync class]
private System.Windows.Forms.Timer _tmrManifestHandler = new System.Windows.Forms.Timer();
public WebSyn()
{
_tmrManifestHandler.Tick += new EventHandler(_tmrManifestHandler_Tick);
_tmrManifestHandler.Interval = 100;
_tmrManifestHandler.Enabled = false;
}
public delegate void delBeginSync();
public event delBeginSync evBeginSync;
public void PreConnect()
{
while (true)
{
if (some condition met)
{
evBeginSync();
return ;
}
}
}
public void Connect()
{
_tmrManifestHandler.Enabled = true;
_tmrManifestHandler.Start();
}
private void _tmrManifestHandler_Tick(object sender, EventArgs e)
{
//NOT BEING 'HIT'
}
You have to call _tmrManifestHandler.Start(); enabling is not enough.
Using a System.Windows.Forms.Timer on another thread will not work.
for more info look here.
Use a System.Timers.Timer instead, be carefull of CrossThreadExceptions if you are using accessing UI elements.
public class WebSync
{
private System.Timers.Timer _tmrManifestHandler = new System.Timers.Timer();
public WebSync(object id)
{
_tmrManifestHandler.Elapsed += new System.Timers.ElapsedEventHandler(_tmrManifestHandler_Tick);
_tmrManifestHandler.Interval = 100;
_tmrManifestHandler.Enabled = false;
}
public delegate void delBeginSync();
public event delBeginSync evBeginSync;
public void PreConnect()
{
while (true)
{
if (true /* just for testing*/)
{
evBeginSync();
return;
}
}
}
public void Connect()
{
_tmrManifestHandler.Enabled = true;
_tmrManifestHandler.Start();
}
private void _tmrManifestHandler_Tick(object sender, EventArgs e)
{
//NOT BEING 'HIT'
}
}

Windows Service + read from database

I am new To windows service. I need a windows service that reads an entry from a table from database. I have a CONSOLE APP where I add new project WINDOWS SERVICE. I already have a method that access the database, and other methods. I can put a thread on start that reads the database. Where do I put the thread? ( how can I do that). Where on WINDOWS SERVICE I add those methods? I have the Windows Service like this:
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
do
{
thread.start();
bool variab = readFromDatabase (Database table);
}
}
protected override void OnStop()
{
}
I suggest that you create a class in which you do everything you need and create in in the service:
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
YourClass cl = new YourClass();
cl.DoWhatYouNeed(...);
}
protected override void OnStop()
{
}
This gives you opportunity to run and test your class separate from service, maybe during debug release.
With windows services usually a method is created to execute the main loop of the service, in a separated thread. Otherwise the service could become unresponsive. For example, you can have a method called MainLoop to execute the service logic. Use the OnStart method only to do the initializing tasks, such as read configuration values or start the threads of the service. And use the OnStop to executing cleaning tasks, stopping threads, etc...
Thread _workerThread;
bool _shouldStop;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try{
_workerThread = new Thread(new ThreadStart(MainLoop));
_shouldStop = false;
_workerThread.Start();
}
catch{}
}
private void MainLoop()
{
while (!_shouldStop)
{
try{
//your logic here
}
catch{}
}
}
protected override void OnStop()
{
_shouldStop = true;
}
You must put your code or class, which contain data access logic in OnStart method

Categories

Resources