My company has developed a Windows Service Application and it was installed in some customers.
They are complaining that the Service stops after continuously running for a few days.
I can't reproduce the error and I do not have any stack trace. All I have is a generic message in Event Viewer:
The 'myservicename' service terminated unexpectedly. It has done this 1 time(s).
My code:
private System.Timers.Timer myTimer;
private readonly Queue<FileInfo> MyQueue = new Queue<FileInfo>();
protected override void OnStart(string[] args)
{
myTimer = new System.Timers.Timer(1000 * 60 * 1); // 1 min
myTimer.Elapsed += new ElapsedEventHandler(MyMethod);
myTimer.Start();
SomeSafeTasks();
try
{
CreateSomeThreads();
}
catch(Exception)
{
//log
}
}
public void MyMethod()
{
lock (MyQueue) // there are other places with lock
{
if(MyQueue.Count == 0)
{
// code with try catch
}
}
}
I believe that the error is related with the Timer being GC'ed.
Does it make sense? The code above may break after running some days?
How do I estimate when it will break? It is strange for me that it runs for a week. I would expect that it would be GC'ed in 15 minutes or 1 hour.
Is it 100% safe to add GC.KeepAlive(myTimer) after myTimer.Start()?
Will it run forever or do I need to call GC.KeepAlive sometimes?
Related
after reading this stack overflow page and this other one.
I didn't really found an answer to my question, I was asking myself why is my service stopping after one loop althought is works fine in debug mode (visual studio).
Here is the code I have
public partial class Service1 : ServiceBase
{
Timer t;
// some more stuff
public Service1()
{
InitializeComponent();
// some more stuff
t = new Timer();
t.Interval = 1000 * 5; // timer of 5 secs.
t.Elapsed += new ElapsedEventHandler(this.onTimer);
t.Start();
}
protected void onTimer(object sender, ElapsedEventArgs args)
{
t.Stop(); // stop the timer to prevent callung the function 2 times in parallel
int tag = 1;
while (tag == 1)
{
tag = doStuff(); // return 1 if it needs to continu looping, return 0 when done
}
t.Start();
}
}
My problem is that doStuff() gets called one time, loop only once, and never get called again (I know this thanks to a log.txt file that I din't show up in the exemple)
I have created a windows service that reads an IBM MQ messages and processes them. My Win Service is currently designed OnStart it triggers a timer interval which calls the function that calls the class which does all the work (See code below).
What I am trying to accomplish is to scale (if that is the right word) the application, if there are a lot of messages on the queue to process we would like to run multiple instances/threads of the service. Ideal situation would be to have some type of configuration in the app.config that indicates how many threads or worker processes to have running. Is threading the right approach? Is there a better or preferred way? Right now what we are doing is installing a new instance of the service with a different name and it is getting quiet tedious.
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("Service Started", EventLogEntryType.Information);
_myTimer.Interval = 500; // half a second
_myTimer.Elapsed += OnTimer;
_myTimer.AutoReset = false;
_myTimer.Enabled = true;
}
public void OnTimer(object sender, ElapsedEventArgs args)
{
//If you want the main program to go ahead and shut down after some period of time, regardless of whether it's obtained the lock, use Monitor.TryEnter. For example, this will wait 15 seconds.
//bool gotLock = Monitor.TryEnter(_timerLock, TimeSpan.FromSeconds(15));
if (!Monitor.TryEnter(_timerLock))
{
// something has the lock. Probably shutting down.
return;
}
try
{
MqSyncJob mqSyncJob = new MqSyncJob(eventLog1);
mqSyncJob.ProcessSyncJobQueue();
}
catch (Exception ex)
{
eventLog1.WriteEntry(ex.ToString(), EventLogEntryType.Error);
}
finally
{
_myTimer.Start(); // re-enables the timer
Monitor.Exit(_timerLock);
}
}
In my application I do check for updates on a SQL Server (the zip files get stored in a varbinary(max) column, don't ask why it's done this way, it's just the way it is). The application is checking for a new version with a Timer every 30 minutes.
Now the problem is if the computer goes to sleep and resumes from it after the next timer cycle I always get an "Could not connect to database ..." error. So I though it should be enough to simply stop the Timer when the system goes to standby and resume it when it wakes up.
But it seems like I never even get into the PowerModeChanged Event (I've tried to check with writing logs, because I don't think you can debug this Event really).
The code below shows what I'm trying to do, and is from my App.xaml.cs:
// System.Threading.Timer not System.Timers
private Timer _updateTimer;
private void App_OnStartup(object sender, StartupEventArgs e)
{
// Do update check on startup
...
var updateTime = new TimeSpan(0, 30, 0); // 30 Minutes
// start update checking in 30 minutes and do it every 30 minutes
_updateTimer = new Timer(UpdateCheck, null, updateTime, updateTime);
SystemEvents.PowerModeChanged += (o, args) =>
{
if (args.Mode == PowerModes.Suspend)
_updateTimer.Dispose();
else if (args.Mode == PowerModes.Resume)
_updateTimer = new Timer( ... );
};
}
private void UpdateCheck(object state)
{
if (Settings.Default.AutoUpdate && UpdateAvailable()) {
if (MessageBox.Show( ... ) == MessageBoxResult.Yes)
DoUpdate();
}
}
private bool UpdateAvailable() { ... }
private void DoUpdate() { ... }
Am I using PowerModeChanged the wrong way? Or is this approach not the best idea at all?
You can use try catch and catch the exception where it gives error.When computer sleeps it will throw exception and your program will catch that.Program will not stop and will loop again and again. when computer resumes it will start working as normal.
I am working on a Windows Service that essentially runs the following code:
public class ServiceController
{
private FundsEngine _fundsEngine;
protected override void OnStart(string[] args)
{
var logsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs");
if (Directory.Exists(logsPath) == false)
{
Directory.CreateDirectory(logsPath);
}
_fundsEngine = new FundsEngine();
_fundsEngine.Start();
}
}
The service can start up "Engines" which are just classes that use Timers to execute code on a specified interval.
The following class is an example of an Engine that uses System.Threading.Timer to invoke a callback, OnTick(), every 5 seconds.
public class FundsEngine
{
private System.Threading.Timer _timer;
private static Logger _logger = LogManager.GetCurrentClassLogger();
public void Start()
{
_logger.Trace("Begin Start");
try
{
// details omitted
_timer = new Timer(OnTick);
_timer.Change(5000, Timeout.Infinite);
}
catch (Exception exception)
{
_logger.ErrorException("Error in Start.", exception);
}
finally
{
_logger.Trace("End Start");
}
}
private void OnTick(object state)
{
_logger.Trace("Begin Tick");
try
{
// do stuff
_timer.Change(5000, Timeout.Infinite);
}
catch (Exception exception)
{
_logger.ErrorException("Error in Tick. ", exception);
}
finally
{
_logger.Trace("End Tick");
}
}
}
As shown in the log below, the Timer works as expected, invoking the OnTick() method every 5 seconds.
2013-05-14 16:27:01.2261|TRACE|Begin Start
2013-05-14 16:27:03.8514|TRACE|End Start
2013-05-14 16:27:08.8569|TRACE|Begin Tick
2013-05-14 16:27:08.8709|TRACE|End Tick
2013-05-14 16:27:13.8734|TRACE|Begin Tick
2013-05-14 16:27:13.8734|TRACE|End Tick
2013-05-14 16:27:18.8809|TRACE|Begin Tick
2013-05-14 16:27:18.8809|TRACE|End Tick
2013-05-14 16:27:23.8894|TRACE|Begin Tick
2013-05-14 16:27:23.8894|TRACE|End Tick
2013-05-14 16:27:28.8969|TRACE|Begin Tick
2013-05-14 16:27:28.8969|TRACE|End Tick
2013-05-14 16:27:33.9044|TRACE|Begin Tick
2013-05-14 16:27:33.9044|TRACE|End Tick
In the event that an Exception is caught in the OnTick() method, my expectation is that it will be logged, and the service will continue running, such that the OnTick() method will be invoked again in 5 seconds. However, this is not the case, as the callback is never invoked again after the Exception is handled. Why is this?
2013-05-14 16:29:03.8574|TRACE|Begin Start
2013-05-14 16:29:03.8574|TRACE|End Start
2013-05-14 16:29:08.8709|TRACE|Begin Tick
2013-05-14 16:29:09.9750|ERROR|Error in Tick. System.Net.Sockets.SocketException (0x80004005): No connection could be made because the target machine actively refused it 127.0.0.1:22
2013-05-14 16:29:09.9750|TRACE|End Tick
_timer.Change(5000, Timeout.Infinite);
You didn't create a period timer, passing Infinite for the period argument. The timer will call OnTick() only once. Code is however very incomplete, the only way it could work is when it calls Change() again to recharge the timer.
So high odds that this Change() call is getting bypassed by the exception. If you want to keep it going then this Change() call belongs in the finally block. Although it is not actually a good idea to do this, non-zero odds that the process state is corrupted and it will just crash again. Over and over. You should at least take a countermeasure against this and also count the number of consecutive crashes, giving up when it just bombs repeatedly.
The accepted answer on this StackOverflow post states that in the event of an exception...
System.Threading.Timer will terminate the program.
Which I believe is what you are seeing.
This is my first window service that I am writing, I need some help in writing it, I am trying to use single thread so that one thread can start the service
and the other thread can take care of calling the functions that does the database work. I am also using a timer so that this service only runs once a day below is my code
The reason i am posting this question is whenever I tried to install this service, it is throwing an error saying "fatal error occure", it doen't give me any details.
public partial class Service1 : ServiceBase
{
private DateTime _lastRun = DateTime.Now;
Thread workerThread;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
ThreadStart st = new ThreadStart(WorkerFunction);
workerThread = new Thread(st);
serviceStarted = true;
workerThread.Start();
}
protected override void OnStop()
{
// flag to tell the worker process to stop
serviceStarted = false;
// give it a little time to finish any pending work
workerThread.Join(new TimeSpan(0, 2, 0));
timer1.Enabled = false;
}
private void WorkerFunction()
{
while (serviceStarted)
{
EventLog.WriteEntry("Service working",
System.Diagnostics.EventLogEntryType.Information);
// yield
if (serviceStarted)
{
Thread.Sleep(new TimeSpan(0, 20000, 0));
}
timer1.Enabled = true;
timer1.Start();
}
// time to end the thread
Thread.CurrentThread.Abort();
}
private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (_lastRun.Date < DateTime.Now.Date)
{
timer1.Stop();
// does the actual work that deals with the database
}
timer1.Start();
}
There's a few things to check:
Be sure that you have configured the EventLog source correctly (MSDN). My answer to Windows service Started and stopped automatically, exception handling issue could be useful here also.
It looks like you are using a Windows Forms Timer - these require a UI message pump, which you won't have in a service (MSDN). You should instead investigate using the Timer class in the System.Threading namespace (MSDN).
In particular, you may find the using a System.Threading.Timer will simplify your code a great deal as this object will manage a bit more of the plumbing for you.
I would also advise against calling Thread.Abort(): it can be harmful and unpredictable, and in your case it doesn't appear that you need to use it at all. See To CurrentThread.Abort or not to CurrentThread.Abort and
http://msdn.microsoft.com/en-us/library/5b50fdsz.aspx.