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...
Related
I have created a Windows Service using Topshelf that is meant to run on a fixed schedule and continue running every day. I am able to install the service and when I start it, it will run correctly during that day.
The problem that I encounter is that at the end of each day, the service stops polling. It no longer writes out to the log to indicate that the service is running or that the timer is tracking. Windows still lists this service as running, with the option to either stop or restart. I can manually restart the service which will let the service run until the end of the day. However, once the day ends and a new day begins, the service no longer seems to be running.
I have made some attempts to modify the settings for this service with no success. Is there a configuration value that needs to be set in order to let the service keep running without the need for a manual restart every day?
This is the relevant code for program.cs:
namespace MyService
{
class Program
{
static void Main(string[] args)
{
{
HostFactory.Run(x =>
{
x.Service<ServiceManager>(s =>
{
s.ConstructUsing(FileProcess => new ServiceManager());
s.WhenStarted(FileProcess => FileProcess.Start());
s.WhenStopped(FileProcess => FileProcess.Stop());
});
x.StartAutomatically();
x.RunAsLocalSystem();
x.EnableServiceRecovery(recoverOption =>
{
recoverOption.RestartService(1);
recoverOption.RestartService(5);
recoverOption.TakeNoAction();
});
x.SetServiceName("MyService");
x.SetDisplayName("MyService v1.0");
x.SetDescription("This is the description for MyService.");
});
}
}
}
}
And the relevant code for ServiceManager.cs:
namespace MyService
{
public class ServiceManager
{
private readonly Timer _timer;
private static Logger logger = LogManager.GetCurrentClassLogger();
public ServiceManager()
{
logger.Info("Service manager start");
ConfigurationManager.RefreshSection("appSettings");
ConfigurationManager.RefreshSection("connectionStrings");
//Converts TimerInterval from app.config into minutes. Timer elapses every (TimerInterval) minutes.
Double timerInterval = (Convert.ToDouble(ConfigurationManager.AppSettings["TimerInterval"]) * 1000 * 60);
_timer = new Timer(timerInterval) { AutoReset = true };
_timer.Elapsed += TimerElapsed;
logger.Info("Service manager end");
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
TaskManager tm = new TaskManager();
tm.Run();
}
public void Start()
{
logger.Debug("Start service");
_timer.Start();
}
public void Stop()
{
logger.Debug("Stop service");
_timer.Stop();
}
}
}
I have developed a Windows Service capable of running a few plugins. Due to its nature, when developing Windows Services, the Start and Stop methods should run and return as fast as possible. The Start method runs Start methods from all plugins, which also should not block the execution. In this example, both plugins instantiate a Threading.Timer, which run in background.
The execution order happens as follows. The arrows indicate what runs in a different thread:
-> MyService.Start -> pA.Start -> pb.Start -> return
\_> DoWork() \
\_> DoWork()
Since both DoWork() are running inside a Timer, if an Exception happens, I am unable to catch it. This could easily be avoided if I could modify PluginA and PluginB, but I can't.
Any suggestion on what I could do to avoid this issue? Thanks in advance.
The following code is an oversimplification of the real code:
public class MyService
{
private PluginA pA = new PluginA();
private PluginB pB = new PluginB();
// Windows Service runs Start when the service starts. It must return ASAP
public void Start()
{
// try..catch doesn't capture PluginB's exception
pA.Start();
pB.Start();
}
// Windows Service runs Stop when the service Stops. It must return ASAP
public void Stop()
{
pA.Stop();
pB.Stop();
}
}
// I have no control over how this is developed
public class PluginA
{
private Timer _timer;
public void Start()
{
_timer = new Timer(
(e) => DoWork(),
null,
TimeSpan.Zero,
TimeSpan.FromSeconds(10));
}
private void DoWork()
{
File.AppendAllText(
"C:/log.txt",
"hello" + Environment.NewLine);
}
public void Stop()
{
_timer.Change(Timeout.Infinite, 0);
}
}
// I have no control over how this is developed
public class PluginB
{
private Timer _timer;
public void Start()
{
_timer = new Timer(
(e) => DoWork(),
null,
TimeSpan.Zero,
TimeSpan.FromSeconds(10));
}
private void DoWork()
{
File.AppendAllText(
"C:/log.txt",
"Goodbye" + Environment.NewLine);
throw new Exception("Goodbye");
}
public void Stop()
{
_timer.Change(Timeout.Infinite, 0);
}
}
You can also use the AppDomain.UnhandledException Event.
Please note that you can't recover from such an exception.
The windows service i coded is not working:
Intended funcionality: The service is supposed to receive messages from Windows Message Queue (MSMQ) and write the messages on .txt files.
It works when I run it not-as-a-service (directly from visual studio)
When I installed it as a service i can start it, but it doesn't do anything, not creating/writing .txt files anywhere
(I know it isn't writing the files elsewhere because when I run the program from VS the messages are still in the queue, so they weren't taken out by the service)
The difference between running it as a service and running it from visual studio is the next:
namespace ComponentAtrapador
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
#if DEBUG
Service1 myService = new Service1();
myService.startMethod();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
#endif
}
}
}
(so if i run it as DEBUG it will run without me having to install it as a service)
Here's the service's code:
namespace ComponentAtrapador
{
public partial class Service1 : ServiceBase
{
private System.Timers.Timer _timer;
private System.ComponentModel.IContainer components1;
private System.Diagnostics.EventLog eventLog1;
public void startMethod()
{
OnStart(null);
}
public Service1()
{
InitializeComponent();
eventLog1 = new System.Diagnostics.EventLog();
if (!System.Diagnostics.EventLog.SourceExists("MySource"))
{
System.Diagnostics.EventLog.CreateEventSource(
"MySource", "MyNewLog");
}
eventLog1.Source = "MySource";
eventLog1.Log = "MyNewLog";
}
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart");
_timer = new System.Timers.Timer();
_timer.Interval = 5000; // 5 seconds
_timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
_timer.Start();
}
protected override void OnStop()
{
_timer.Stop();
}
public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
string nombreArchivo = "archivoMensaje";
MessageQueue messageQueue = new MessageQueue(#".\Private$\SomeTestName");
System.Messaging.Message[] messages = messageQueue.GetAllMessages();
System.Messaging.Message m = new System.Messaging.Message();
foreach (System.Messaging.Message message in messages)
{
message.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
string text = message.Body.ToString();
System.IO.File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + nombreArchivo + Properties.Settings.Default.SettingNumero + ".txt", text);
Properties.Settings.Default.SettingNumero++;
Properties.Settings.Default.Save();
//Do something with the message.
}
// after all processing, delete all the messages
messageQueue.Purge();
//}
}
}
}
That is where Logs are so helpful, put couple of eventLog1.WriteEntry() inside your OnTimer method and you will see where is it failing.
I would check
how many messages I am getting.
I will put one eventLog1.WriteEntry() inside loop to see what is happening with each message etc...
Turns out the service didn't have enough permissions, fixed it by setting the serviceProcessInstaller of the service on visual studio to User, so that when i installed it it'd ask for credentials. Just had to type "./[username]" when it asked for my username for it to work.
Another way of fixing it would be going into the task manager > services > right click service > properties > security. And change the permissions there.
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.
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