This question already has answers here:
Better way to constantly run function periodically in C#
(3 answers)
Closed 2 years ago.
Id like to build a windows Service in C#.
This service needs to be run periodically like every 10s.
Questions:
What is the difference between Timers.timer and Threading.timer?
How can I call CheckingThings with parameters?
If i run this code, it does invoke CheckingThings more than once every second like declared in here:
_timer = new Timer(new TimerCallback(CheckingThings), autoEvent, 5000, 1000);
Here is what i've got so far:
public partial class WindowsService1 : ServiceBase
{
// Logging
private static Serilog.Core.Logger _logEvent;
public WindowsService1()
{
InitializeComponent();
}
public void OnDebug() {
OnStart(null);
}
protected override void OnStart(string[] args)
{
//Logging
try {
_logEvent = new LoggerConfiguration()
.WriteTo.File(AppDomain.CurrentDomain.BaseDirectory + #"Logs\Logfile.txt", rollingInterval: RollingInterval.Month)
.CreateLogger();
}
catch (Exception e)
{
_logEvent.Error("The logging service is not working as expected: {errorMsg}", e);
}
try
{
// initializing some data here
var autoEvent = new AutoResetEvent(true);
while (true)
{
_timer = new Timer(new TimerCallback(CheckingThings), autoEvent, 5000, 1000);
}
}
catch (Exception e) {
_logEvent.Error("An error occured while initializing service: {0}", e);
}
}
private static void CheckingThings(object stateInfo)
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
//These things needs to run periodically every 10s
}
protected override void OnStop()
{
_logEvent.Information("Stopping Service ...");
}
}
Here's a skeleton for a service class that does something every minute, using a System.Timers.Timer:
public partial class XService : ServiceBase
{
private Timer _minute = new Timer(60000);
public XService()
{
InitializeComponent();
_minute.Elapsed += Minute_Elapsed;
}
//this is async because my 'stuff' is async
private async void Minute_Elapsed(object sender, ElapsedEventArgs e)
{
_minute.Stop();
try
{
//stuff
}
catch (Exception ex)
{
//log ?
}
finally
{
_minute.Start();
}
}
protected override void OnStart(string[] args)
{
_minute.Start(); //this or..
Minute_Elapsed(null, null); //..this, if you want to do the things as soon as the service starts (otherwise the first tick will be a minute after start is called
}
...
I typically stop my timers while I do my thing - no point starting a job that takes 10 minutes and then another one a minute later, hence the stop/try/finally/start pattern
Edit:
Here's the tail part of the class and how it's started/launched both in debug (inside visual studio) and in release (as an installed windows service):
//just an adapter method so we can call OnStart like the service manager does, in a debugging context
public void PubOnStop()
{
OnStop();
}
}// end of XService class
static void Main(string[] args)
{
#if DEBUG
new XService().PubStart(args);
Thread.Sleep(Timeout.Infinite);
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new XService()
};
ServiceBase.Run(ServicesToRun);
#endif
}
Related
How do I use "StartService" Task with ThreadStart?
Is it possible?
public partial class MyService : ServiceBase
{
public MyService()
{
InitializeComponent();
LocalInit();
}
internal void LocalInit()
{
//place here any local checks
}
protected override void OnStart(string[] args)
{
if (Something.ConfigOK())
{
ThreadStart threadDelegate = Something.StartService; // Expected a method with void StartService signature
var newThread = new Thread(threadDelegate);
newThread.Start();
}
else
{
//log error
throw new Exception("MyService : Config failed");
}
}
}
public static partial class Something
{
public static async Task StartService()
{
await DoJob();
}
}
Errors
Error CS0407 'Task Something.StartService()' has the wrong return type
Expected a method with void StartService signature
Have you tried this?
protected override void OnStart(string[] args)
{
if (Something.ConfigOK())
{
Something.StartService();
}
else
{
//log error
throw new Exception("MyService : Config failed");
}
}
If DoJob os truly asynchronous or:
protected override void OnStart(string[] args)
{
if (Something.ConfigOK())
{
Task.Run(Something.StartService);
}
else
{
//log error
throw new Exception("MyService : Config failed");
}
}
if it isn't (blocking).
There's no need to explicitly create a thread.
Beware of exception handling!
But, since you mention ASP.NET Core (???) I would recomend using a Worker template.
It is possible, but I would suggest you to go with Background tasks with hosted services.
Here is some implementation
Or use hangfire queues.
As I mentioned, this is a suggestion not a answer for your question.
I have created a windows service using .Net framework 4.7 with C# as the language. This service basically fetches computer hardware information (CPU usage) and writes it to a log file (using log4net). After compiling the service in release mode, when i installed it using installutil, the service is created and upon starting the service, a file with same name as 'exe' file with extension of 'sys' gets created frequently and deleted as well. Now when i stop the service, it is no longer created. I have created few windows services in the past using .Net but never encountered such behavior.
Program.cs
static void Main()
{
#if DEBUG
Service serv = new Service();
serv.StartIt();
Thread.Sleep(20000);
serv.StopIt();
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service()
};
ServiceBase.Run(ServicesToRun);
#endif
}
Service.cs
Timer timer = null;
public Service()
{
InitializeComponent();
timer = new Timer(1000);
timer.Elapsed += Timer_Elapsed;
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
SystemInfo si = new SystemInfo();
si.GetSystemInfo();
}
#if DEBUG
public void StartIt()
{
timer.Start();
}
public void StopIt()
{
timer.Stop();
}
protected override void OnStart(string[] args)
{ }
protected override void OnStop() { }
#else
protected override void OnStart(string[] args)
{
timer.Start();
}
protected override void OnStop()
{
timer.Stop();
}
#endif
Note: I am using OpenHardwareMonitor library to collect hardware information.
Link to the problem description
I wanted to create a service which runs automatically on everyday at 4.00 am, and that method would delete some files automatically when it is called, i have written the code but my method which i am calling in service is not getting executed. Below i have attached my code , please somebody suggest me a solution.
public partial class Scheduler : ServiceBase
{
System.Timers.Timer _timer;
public Scheduler()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
_timer = new System.Timers.Timer();
_timer.Interval = 1 * 60 * 1000;//Every one minute
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
_timer.Start();
}
catch (Exception ex)
{
Library.WriteErrorLog(ex);
}
}
public void timer_Elapsed(object sender, ElapsedEventArgs e)
{
Library.WriteErrorLog("Timer elapsed");
this.ExtractDataFromSharePoint();
}
public void ExtractDataFromSharePoint()
{
Library.WriteErrorLog("inside task");
ArchiveAdministration admin = new ArchiveAdministration();
admin.ArchiveAuto();
Library.WriteErrorLog("job completed");
_timer.Stop();
}
}
And my log file has only the following output statements:
Timer Elapsed
inside task
I am not getting " Job completed " statement which i have included..
Since you are not getting to the line Job completed, then it will be helpful to add a try catch clause in your ExtractDataFromSharePoint method:
public void ExtractDataFromSharePoint()
{
try
{
Library.WriteErrorLog("inside task");
ArchiveAdministration admin = new ArchiveAdministration();
admin.ArchiveAuto();
Library.WriteErrorLog("job completed");
_timer.Stop();
}
catch(Exception ex)
{
Library.WriteErrorLog(ex.Message); //or try to log the stacktrace also
}
}
Catch the exception and if you couldn't solve it, paste it here to be able to help you with that
I have started building up the windows service in the c# language. And i want to implement the timer feature inside it. But for some reason, the DoIt timer event handler is not getting fired during the debugging and i am not getting any exception also. I am trying to debug the windows service using Debug->Start new instance.
The line TraceLog.WriteTrace("Router Service Started"); does get hit and executed.
public partial class EntryPoint : ServiceBase
{
private const int TIMER_INTERVAL = 10000;
private System.Timers.Timer mvTimer = new System.Timers.Timer();
[MTAThread()]
[System.Diagnostics.DebuggerNonUserCode()]
public static void Main()
{
#if DEBUG
EntryPoint service = new EntryPoint();
service.Start();
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new EntryPoint()
};
ServiceBase.Run(ServicesToRun);
#endif
}
public EntryPoint()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
InitializeComponent();
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception ex = (Exception)e.ExceptionObject;
if (ex != null)
{
Console.WriteLine(ex);
}
}
public void Start()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
TraceLog.SetTrace(ConfigurationManager.AppSettings["RouterTraceLog"]);
TraceLog.WriteTrace("Router Service Started");
mvTimer = new Timer();
mvTimer.Elapsed += new ElapsedEventHandler(DoIt);
try
{
mvTimer.Interval = TIMER_INTERVAL;
mvTimer.Enabled = true;
}
catch (Exception ex)
{
mvTimer.Interval = TIMER_INTERVAL;
TraceLog.WriteTrace(ex.Message);
}
}
private void DoIt(object sender, ElapsedEventArgs e)
{
TraceLog.WriteTrace("Inside DoIt :: " + DateTime.UtcNow.ToString());
}
protected override void OnStop()
{
mvTimer.Enabled = false;
TraceLog.WriteTrace("Router Service stopping");
}
Please suggest. I am missing something very small and not able to nail it down.
In debug mode, the application exits after the function OnStart finishes. There's nothing to stop the application from quitting.
What you need is add a Console.ReadLine(); to prevent the application from exiting.
#if DEBUG
EntryPoint service = new EntryPoint();
service.Start();
Console.ReadLine();
#else
You can read more at MSDN on How to: Debug Windows Service Applications
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.