I created a windows service project with Visual Studio. This service should run in the background and poll data every X seconds. The polling is achieved with a timer and a tick event. So whenever the tick event is raised the service should do something.
Unfortunately the service closes itself because it does not wait for the timer to tick. The OnStart method gets executed and runs but after that the service closes itself.
I added a debug mode to my program file
private static void Main()
{
#if DEBUG
new RuntimeService().RunDebugMode();
#else
ServiceBase.Run(new RuntimeService());
#endif
}
and use this code for my service application
public partial class RuntimeService : ServiceBase
{
private const int BATCH_POLLING_INTERVAL = 3000;
private Timer batchPollingTimer;
public RuntimeService()
{
InitializeComponent();
}
public void RunDebugMode()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
try
{
// ...
batchPollingTimer = new Timer(BATCH_POLLING_INTERVAL);
batchPollingTimer.Elapsed += OnTimer;
batchPollingTimer.Enabled = true;
}
catch (Exception exception)
{
throw exception;
}
}
protected override void OnStop()
{
batchPollingTimer.Enabled = false;
try
{
// ...
}
catch (Exception exception)
{
throw exception;
}
}
private void OnTimer(object sender, ElapsedEventArgs e)
{
batchPollingTimer.Enabled = false;
// ...
batchPollingTimer.Enabled = true;
}
}
How can I run the service without closing it and waiting for the timer ticks? By "closing itself" I mean executing the Main method and ignoring the timer. Please let me know if you need more information.
It will only do this in debug mode, because there is nothing stopping it from ending. Ordinarily ServiceBase.Run will not return unless the service is shutting down. Add a sleep for a long time so that after your main thread has kicked off your timer, it will go to sleep rather than exiting the Main
Something like:
private static void Main()
{
#if DEBUG
new RuntimeService().RunDebugMode();
System.Threading.Thread.Sleep(TimeSpan.FromDays(1));
#else
ServiceBase.Run(new RuntimeService());
#endif
}
As an aside, consider putting your timer stop/start in a try/finally - at the moment if something happens in your OnTimer, your stopped timer will never restart and your service will cease doing anything (but may not crash entirely)
private void OnTimer(object sender, ElapsedEventArgs e)
{
try{
batchPollingTimer.Enabled = false;
// ...
} finally {
batchPollingTimer.Enabled = true;
}
}
}
Related
I have a windows service application. I want this windows service to run a method after every x minutes. I also want when the existing method is running, it should not allow the timer method to execute. I have,
private static readonly ILogger Logger = GetLogger();
private Timer _timer;
protected override void OnStart(string[] args)
{
Logger.Log("Starting Timer");
StartTimer();
}
protected override void OnStop()
{
Logger.Log("Stoping Timer");
StopTimer();
}
private void Timer_Elapsed(object state)
{
Logger.Log("Timer Elapsed");
DoWork();
RestartTimer();
}
private static void DoWork()
{
try
{
// Doing my work there
}
catch (Exception ex)
{
Logger.Log(ex);
}
}
private void StartTimer()
{
Logger.Log("Running first time manually");
ThreadPool.QueueUserWorkItem((_) => DoWork());
var frequency = GetTimerFrequency();
_timer = new Timer(Timer_Elapsed, null, frequency, Timeout.Infinite);
}
private void RestartTimer()
{
var frequency = GetTimerFrequency();
_timer.Change(frequency, Timeout.Infinite);
}
private void StopTimer()
{
_timer.Change(Timeout.Infinite, Timeout.Infinite);
_timer.Dispose();
_timer = null;
}
I dunno why but some-times when the method DoWork is running, Timer_Elapsed is executing. I want until one DoWork finished, no more DoWork is allowed to execute.
Possible Duplicate of this post. You have to check the status of the app whether its already running or not.
Here
My timer elapsed event does not fire in my windows service, why? I search in the forum but nothing of the solutions work for me.
In the main of program.cs:
static class program
{
static void Main()
{
#if DEBUG
servicioCR cr = new servicioCR();
cr.beginProcess();
#else
#endif
//ServiceBase[] ServicesToRun;
//ServicesToRun = new ServiceBase[]
//{
// new servicioCR()
//};
//ServiceBase.Run(ServicesToRun);
}
}
In my service class
public static System.Timers.Timer timer;
public servicioCR()
{
timer = new System.Timers.Timer(5000);
timer.AutoReset = false;
timer.Elapsed += timer_Elapsed;
InitializeComponent();
}
The elapsed event
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
timer.Stop();
//Do stuff
}
catch (System.Exception ex)
{
EventLog.WriteEntry(ex.Message);
}
finally
{
timer.Start();
}
}
And the beginProcess()
internal void beginProcess()
{
timer.Start();
}
I am using .NET Framework 4.5 and VS 2013... I don't understand why it doesn't work, I copied this from another solution that works fine.
If I put a breakpoint in one line of the Do stuff on the elapsed event, it never breaks.
Why? Thanks
Your timer is running, but the program closes itself before the timer ever fires. You need to put a pause of some kind in so your program does not close itself.
static void Main()
{
#if DEBUG
servicioCR cr = new servicioCR();
cr.beginProcess();
Console.WriteLine("Program Running");
Console.ReadLine();
#else
#endif
//ServiceBase[] ServicesToRun;
//ServicesToRun = new ServiceBase[]
//{
// new servicioCR()
//};
//ServiceBase.Run(ServicesToRun);
}
Here is a snippit of code from one of my older projects, this lets you run your program as both a service and a console app. In Visual studio just set the debugger to pass in the arguments --console in the setup project screen.
class Program
{
public static void Main(string[] args)
{
var example = new MyExampleApp();
if (args.Contains("--console"))
{
example.ConsoleRun(args);
}
else
{
ServiceBase.Run(example);
}
}
}
class MyExampleApp : ServiceBase
{
public void ConsoleRun(string[] args)
{
Console.WriteLine(string.Format("{0}::starting...", GetType().FullName));
OnStart(args);
Console.WriteLine(string.Format("{0}::ready (ENTER to exit)", GetType().FullName));
Console.ReadLine();
OnStop();
Console.WriteLine(string.Format("{0}::stopped", GetType().FullName));
}
//... the rest of the code from your service class.
}
I made a thread at load event like below:
Thread checkAlert = null;
bool isStop = false;
private void frmMain_Load(object sender, EventArgs e)
{
checkAlert = new Thread(CheckAlert);
checkAlert.Start();
}
void CheckAlert()
{
while (!isStop)
{
Thread.Sleep(60000);
//do work here
}
}
Is there any way to resume the checkAlert thread during it's sleep period?( Thread.Sleep(60000);)
I tried using Thread.Interrupt() but it flows a ThreadInterruptedException, how should I handle this exception? or is there any way to resume the thread?
Edited:
I need to wake up the thread before the "sleep" end because when the user wants to quit the program, the program will have to wait for some time before it really quits ( checkAlert is still running) Is there any way to improve this case?
Based on your comments what it looks like is you need to re-design how CheckAlert works so it does not use Sleep's at all. What you should be doing is using a Timer instead.
System.Timers.Timer timer = null;
public FrmMain()
{
InitializeComponent();
timer = new System.Timers.Timer(60000);
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
//If you want OnTimedEvent to happen on the UI thread instead of a ThreadPool thread, uncomment the following line.
//timer.SynchronizingObject = this;
if(this.components == null)
this.components = new System.ComponentModel.Container();
//This makes it so when the form is disposed the timer will be disposed with it.
this.componets.Add(timer);
}
private void frmMain_Load(object sender, EventArgs e)
{
timer.Start();
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
//It is good practice not to do complicated logic in a event handler
// if we move the logic to its own method it is much easier to test (you are writing unit tests, right? ;) )
CheckAlert();
}
void CheckAlert()
{
//do work here
}
private void frmMain_Close(object sender, EventArgs e)
{
timer.Stop();
}
If you want the thread to exit automatically when your program quits, simply make it a background thread.
checkAlert = new Thread(CheckAlert);
checkAlert.IsBackground = true;
checkAlert.Start();
It looks to me like you're trying to create a thread which handles two types of events: do something and stop running.
Rather than using a shared variable (isStop) and some other technique to interrupt the thread in order to do work, you might want to use threading events (not to be confused high-level UI Event objects) to control your thread.
AutoResetEvent stop = new AutoResetEvent(false);
AutoResetEvent check = new AutoResetEvent(false);
private void CheckAlert() {
WaitHandle[] handles = new WaitHandle[] { stop, check };
for (;;) {
switch (AutoResetEvent.WaitAny(handles)) {
case 0:
return;
case 1:
// do work
break;
}
}
}
Calling check.Set() in your code will trigger the "do work" branch in the thread and stop.Set() will cause the thread to terminate gracefully.
Once your code has called stop.Set() to terminate the thread, it can call the thread's Join() method to wait until the thread terminates.
EDIT
I misunderstood the question. I will leave the code above in case anyone finds it useful.
If all you want to do is have a thread that performs a task once a minute and stop on demand, you can use the following code:
AutoResetEvent stop = new AutoResetEvent(false);
void CheckAlert() {
var time = new TimeSpan(0, 1, 0); // one minute
while (!stop.WaitOne(time)) {
// do work
}
}
private Thread checkThread;
private void frmMain_Load(object sender, EventArgs e) {
checkThread = new Thread(CheckAlert);
checkThread.Start();
}
private void frmMain_Close(object sender, EventArgs e) {
stop.Set(); // signal thread to stop
checkThread.Join(); // wait for thread to terminate
}
You can see an explanation on how to wake a sleeping thread here:
https://msdn.microsoft.com/en-us/library/tttdef8x%28v=vs.100%29.aspx
and this is a complete example (as you can see, Thread.Interrupt is the good choise... however you have to catch it to continue normal thread execution):
public class HVCSensor : HVCDevice, IDisposable
{
private Thread myThread;
private const int execute_timeout = ((10 + 10 + 6 + 3 + 15 + 15 + 1 + 1 + 15 + 10) * 1000);
private bool disposed = false;
private bool paused = false;
public delegate void HVCResultsHandler(HVC_RESULT res);
public event HVCResultsHandler HVCResultsArrived;
private void OnHVCResultsArrived(HVC_RESULT res)
{
if (HVCResultsArrived != null) {
HVCResultsArrived(res);
}
}
public HVCSensor() {
myThread = new Thread(new ThreadStart(this.execute));
}
private void execute(){
while (!disposed) {
if (!paused && this.IsConnected)
{
HVC_RESULT outRes;
byte status;
try
{
this.ExecuteEx(execute_timeout, activeDetections, imageAcquire, out outRes, out status);
OnHVCResultsArrived(outRes);
}
catch (Exception ex) {
}
}
else {
try
{
Thread.Sleep(1000);
}
catch (ThreadInterruptedException e)
{
}
}
}
}
public HVC_EXECUTION_IMAGE imageAcquire
{
get;
set;
}
public HVC_EXECUTION_FLAG activeDetections
{
get;
set;
}
public void startDetection() {
if(myThread.ThreadState==ThreadState.Unstarted)
myThread.Start();
}
public void pauseDetection() {
paused = true;
}
public void resumeDetection() {
paused = false;
if (myThread.ThreadState == ThreadState.WaitSleepJoin)
myThread.Interrupt();
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
disposed = true;
myThread.Interrupt();
}
}
I have some code where the timer EventHandler has this
void timer_Tick(object sender, EventArgs e)
{
try
{
timerRescan.Stop();
ScanForIeInstances()
}
catch (Exception ex)
{
log.Warn("Exception 3", ex);
}
finally
{
timerRescan.Start();
}
}
Naturally there is a race condition with an external entity who may want to Stop the timer down....if the timer is in process and using a thread and someone calls timerRescan.Stop, the timer thread will call Start starting the timer back up again. I am trying to replace this code. There are two methods in java I know and I would like to know how to do both in C#
Run a task every 5 seconds where 5 seconds is the distance between tasks firing
Run a task and AFTER it ends+5seconds run the task again
I would like to use #2 and always fire 5 seconds from the END of the last firing of the event. How do I do that and which timer do I use in C# for that?
This then allows me to have a recurring timer, call start once and have no race condition with the stop(I would rather not have to implement synchronization though I know I could do that as a last resort...would rather just keep the code clean like I can in java)
OR IF you know java, what I am simply looking for is the equivalent of
ScheduledExecutorService.scheduleAtFixedRate - start to start
ScheduledExecutorService.scheduleWithFixedDelay - end to start
A quick way to handle this is to have the external entity set a flag, and then check to see whether that flag has been set:
public bool StopRequested {get; set;}
void timer_Tick(object sender, EventArgs e)
{
if (timerRescan != null) timerRescan.Stop();
if (StopRequested) return;
try
{
ScanForIeInstances()
}
catch (Exception ex)
{
log.Warn("Exception 3", ex);
}
finally
{
timerRescan.Start();
}
}
This doesn't solve the problem if the external entity has a handle on the timer, but the timer should probably be private anyway.
If your only concern is that an external source may want to stop the timer, your best bet is to write a wrapper around this timer that checks a semaphore of sorts....
I have not done any testing of this, but you should be able to grasp the general idea.
public class TimerWrapper
{
public event EventHandler Elapsed;
private System.Timers.Timer timer;
private System.Threading.ManualResetEvent stopped;
private object lockObject = new object();
public TimerWrapper(double interval)
{
stopped = new System.Threading.ManualResetEvent(false);
timer = new System.Timers.Timer(interval);
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock (lockObject)
{
timer.Stop();
try
{
Elapsed(this, new EventArgs());
}
finally
{
if (!stopped.WaitOne(0)) timer.Start();
}
}
}
public void Start()
{
stopped.Reset();
lock (lockObject)
{
timer.Start();
}
}
public void Stop()
{
stopped.Set();
lock (lockObject)
{
timer.Stop();
}
}
}
I'm building a Windows Service using System.Timers.Timer. The tasks computed by the Timer's delegate can take from several seconds to several minutes. I would like to make sure that, when the service is stopped, all delegated threads currently running complete before being disposed.
Here is the code, however it does not do what I expect, as currently running threads never complete if the Windows Service is stopped while they are running.
public abstract class AgentServiceBase : ServiceBase
{
private System.ComponentModel.IContainer components = null;
private System.Timers.Timer _Timer;
private string _logPath;
private const int MAXNUMBEROFTHREADS = 10;
protected int interval = 25000;
protected int numberOfAllowedThreads = 2;
public AgentServiceBase()
{
this.InitializeComponent();
this._logPath = (Path.GetDirectoryName(Assembly.GetAssembly(this.GetType()).CodeBase)).Substring(6).Replace("/", #"\");
}
protected override void OnStart(string[] args)
{
if (args.Length > 0)
{
int.TryParse(args[0], out interval);
}
if (args.Length > 1)
{
int.TryParse(args[1], out numberOfAllowedThreads);
if (numberOfAllowedThreads > MAXNUMBEROFTHREADS)
{
numberOfAllowedThreads = MAXNUMBEROFTHREADS;
}
if (numberOfAllowedThreads == 1)
{
numberOfAllowedThreads = 2;
}
}
ThreadPool.SetMaxThreads(numberOfAllowedThreads, numberOfAllowedThreads);
this._Timer = new System.Timers.Timer();
this._Timer.Elapsed += new ElapsedEventHandler(PollWrapper);
this._Timer.Interval = this.interval;
this._Timer.Enabled = true;
}
protected override void OnStop()
{
this._Timer.Enabled = false;
Process currentProcess = Process.GetCurrentProcess();
foreach (Thread t in currentProcess.Threads)
{
t.Join();
}
}
/// <summary>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
this.ServiceName = "Agent Service - Johnhenry";
}
private void PollWrapper(object sender, ElapsedEventArgs e)
{
try
{
this.Poll(sender, e);
}
catch (Exception exception)
{
string message = this.GetType().FullName + " - Windows Service Exception\n";
message += exception.GetNestedExceptionInSingleStringOutput();
FileHelper.Log(message, this._logPath, "exception", FileHelper.LogFileNameChangeFrequency.DAYLY);
}
}
protected abstract void Poll(object sender, ElapsedEventArgs e);
}
Many thanks,
Giuseppe
UPDATE:
After few different attempts with counting the current process's own threads I eventually settled with a simpler solution which is using a counter of the threads the timer had initiated and are still running. Based on that I call the Sleep on the main thread and issue a RequestAdditionalTime until all threads have ended.
Following the revised 2 methods:
protected override void OnStop()
{
this._Timer.Enabled = false;
while (numberOfRunningThreads > 0)
{
this.RequestAdditionalTime(1000);
Thread.Sleep(1000);
}
}
private void PollWrapper(object sender, ElapsedEventArgs e)
{
numberOfRunningThreads++;
try
{
this.Poll(sender, e);
}
catch (Exception exception)
{
string message = this.GetType().FullName + " - Windows Service Exception\n";
message += exception.GetNestedExceptionInSingleStringOutput();
FileHelper.Log(message, this._logPath, "exception", FileHelper.LogFileNameChangeFrequency.DAYLY);
}
finally
{
numberOfRunningThreads--;
}
}
You can achieve that by calling RequestAdditionalTime as long as your threads haven't finished the work yet in your implementation of OnStop inside the loop (before and/or after the call to Join()).
BUT BEWARE that Windows can get impatient and decide to kill your Windows Service - for example during shutdown...
For more information see the MSDN reference at http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.aspx