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