Timer is firing and executing even the first one is not finished? - c#

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

Related

windows service wait for timer and never close on its own

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;
}
}
}

async await not working with Timer

I have a Presence monitor class which is used to detect users active/inactive status. That class has a timer in its Start method which called on application start:
public class PresenceMonitor
{
private volatile bool _running;
private Timer _timer;
private readonly TimeSpan _presenceCheckInterval = TimeSpan.FromMinutes(1);
public PresenceMonitor()
{
}
public void Start()
{
// Start the timer
_timer = new Timer(_ =>
{
Check();
}, null, TimeSpan.Zero, _presenceCheckInterval);
}
private void Check()
{
if (_running)
{
return;
}
_running = true;
// Dowork
}
}
The "Check" method is fired after every one minute. That piece of code is working fine but now my "Do work" methods have become async await so I had to change this Presence Monitor class to something like this:
public class PresenceMonitor
{
private volatile bool _running;
private Timer _timer;
private readonly TimeSpan _presenceCheckInterval = TimeSpan.FromMinutes(1);
public PresenceMonitor()
{
}
public void Start()
{
// Start the timer
var timer = new System.Threading.Timer(async (e) =>
{
await CheckAsync();
}, null, TimeSpan.Zero, _presenceCheckInterval);
}
private async Task CheckAsync()
{
if (_running)
{
return;
}
_running = true;
// await DoworkAsync
}
}
Unfortunately "CheckAsync" method now is getting fired once only instead of every minute. Can you tell me what I am doing wrong here to call async await after regular intervals?
Is there any correct way to do the same?
You could consider creating an event and handler to handle the timer ticks and then invoke your check.
public class PresenceMonitor {
private volatile bool _running;
private Timer timer;
private readonly TimeSpan _presenceCheckInterval = TimeSpan.FromMinutes(1);
public PresenceMonitor() {
Tick += OnTick;
}
public void Start() {
if (_running) {
return; //already running
}
// Start the timer
timer = new System.Threading.Timer(_ => {
Tick(this, EventArgs.Empty);//rasie event
}, null, TimeSpan.Zero, _presenceCheckInterval);
}
private event EventHandler Tick = delegate { };
private async void OnTick(object sender, EventArgs args) {
if (_running) {
return;
}
_running = true;
await DoworkAsync();
}
private Task DoworkAsync() {
//...
}
}
If I understand correctly your requirements, you can get rid of timer and use asynchronous loop.
But you need make Start method asynchronous too
public class PresenceMonitor
{
private volatile bool _running; // possible not needed "volatile" anymore
private readonly int _presenceCheckInterval = 60000; // Milliseconds
public PresenceMonitor()
{
}
public async Task Start()
{
while (true) // may be use some "exit" logic
{
await CheckAsync();
await Task.Delay(_presenceCheckInterval)
}
}
private async Task CheckAsync()
{
if (_running)
{
return;
}
_running = true;
// await DoworkAsync
}
}
Then you can start monitoring
var monitor = new PresenceMonitor();
await monitor.Start();
You can even start monitoring in synchronous way
var monitor = new PresenceMonitor();
monitor.Start(); // Will start monitoring
But approach above is "dangerous" in the way, that any exception thrown inside CheckAsync method will not be propagated. When you start using async-await be ready to "convert" whole application to support it.

Close console application window after key press or automatically after x minutes

I have a console application in Visual Studio 2008, C# and .NET Framework 3.5.
When application finishes to do all the stuff I want to close the windows when user press a key or automatically after some minutes have been elapsed.
So at the end of my application I do:
static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
public static int Main(string[] args)
{
// Do some stuff
Console.WriteLine("Press any key to close this window.");
myTimer.Tick += new EventHandler(TimerEventProcessor);
myTimer.Interval = 5000;
myTimer.Start();
Console.ReadKey();
return 0;
}
private static void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
{
myTimer.Stop();
Environment.Exit(0);
}
The problem here is that window is not close after x minutes has been elapsed and even timer event is never raised since program is blocked waiting for a key (ReadKey).
So how to do it?
Try to move the work to be done into a separate thread:
public static int Main(...)
{
new System.Threading.Thread(Work).Start();
}
private void Work()
{
// work to be done here
}
This way the GUI thread will have time for raising the timer's tick event.
The problem you have is that you are using a Form timer, which is hung up on a UI thread -- for a console app. You are exiting an environment not of the Console.
We need to use the threading timer instead. But, this should be not too much different.
static Timer myTimer;
public static int Main(string[] args)
{
// Do some stuff
Console.WriteLine("Press any key to close this window.");
//Hey, I just met you and this is crazy
myTimer = new Timer(CallMeMaybe, null, 5000, 0);
//so call me maybe
Console.ReadKey();
return 0;
}
//Instead of a tick, we have this
private static void CallMeMaybe(object state)
{
//But here's my number
Environment.Exit(0);
}
I have found a possible solution, but not sure if the best:
static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();
public static int Main(string[] args)
{
// Do some stuff
Console.WriteLine("Press any key to close this window.");
myTimer.Tick += new EventHandler(TimerEventProcessor);
myTimer.Interval = 5000;
myTimer.Start();
// while (!Console.KeyAvailable)
//{
// Application.DoEvents();
// Thread.Sleep(250);
//}
// Above code replaced with:
Console.ReadKey(true);
DisposeTmr();
return 0;
}
private static void DisposeTmr()
{
myTimer.Stop();
myTimer.Dispose();
}
private static void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
{
DisposeTmr();
Environment.Exit(0);
}
Problem with that solution is that this type of timer is synchronous and it is needed to use Application.DoEvents as explained here. Also the timer remains in a suspended state while the UI thread is sleeping so this can cause timer event handler not continue capturing timer events while the main UI thread is sleeping.
To avoid this, there are two options, System.Timers.Timer and System.Threading.Timer. I have implemented System.Threading.Timer solution as below and it works perfectly:
static System.Threading.Timer myTimer;
public static int Main(string[] args)
{
// Do some stuff
Console.WriteLine("Press any key to close this window.");
myTimer = new System.Threading.Timer(TimerCallback, null, 5000, Timeout.Infinite);
while (!Console.KeyAvailable)
{
Thread.Sleep(250);
}
DisposeTmr();
return 0;
}
private static void DisposeTmr()
{
if (myTimer != null)
{
myTimer.Dispose();
}
}
private static void TimerCallback(Object myObject)
{
DisposeTmr();
Environment.Exit(0);
}
This can be implemented pretty easily with async/await.
internal class Program
{
private static async Task Main(string[] args)
{
await DoStuff();
await Task.WhenAny
(
Task.Delay(3000),
ExitOnKeypress()
);
}
private static async Task ExitOnKeypress()
{
while (!Console.KeyAvailable)
{
await Task.Delay(1);
}
}
}

Issue with ballooning threads in periodic processing

I want to do some periodic work on a worker thread which signals when the work is completed. When signaled, I want to wait for 5 seconds and re-do the work. I wrote the following code:
public class WinService : ServiceBase
{
private readonly ManualResetEvent stopPeriodicProcess = new ManualResetEvent(false);
protected override void OnStart(string[] args)
{
stopPeriodicProcess.Reset();
ThreadPool.RegisterWaitForSingleObject(stopPeriodicProcess, InitializeEngines, null,5000, true);
}
public void InitializeEngines(object state, bool timedOut)
{
engine.LoadSettings();
Task.Factory.StartNew(engine.DoSomeWork); //Fire and forget
}
private void WorkCompletedEventHandler(object sender, WorkCompletedEventArgs e)
{
ThreadPool.RegisterWaitForSingleObject(stopPeriodicProcess,
(state, timedOut) => DoPeriodicProcess(state, timedOut, e.EngineId), null,
5000, true);
}
public void DoPeriodicProcess(object state, bool timedOut, string engineId)
{
if (timedOut)
{
Task.Factory.StartNew(engine.DoSomeWork); //Fire and forget
}
}
}
public class Engine
{
public event EventHandler<WorkCompletedEventArgs> WorkCompleted;
public void DoSomeWork()
{
//Doing some work..
//Raise an event to signal that the work has been completed
var args = new WorkCompletedEventArgs {EngineId = Settings.EngineId};
RaiseWorkCompletedEvent(args);
}
protected virtual void RaiseWorkCompletedEvent(WorkCompletedEventArgs e)
{
EventHandler<WorkCompletedEventArgs> handler = WorkCompleted;
if (handler != null)
{
handler(this, e);
}
}
}
When I run the code, the CPU usage shows 100% after few seconds. Upon debugging in VS, I see too many alive worker threads waiting at RegisterWaitForSingleObject inside WorkCompletedEventHandler.
Why aren't the threads dying after calling RegisterWaitForSingleObject? Am I missing something?
Not tested but I think this is due to the event not being reset:
private void WorkCompletedEventHandler(object sender, WorkCompletedEventArgs e)
{
stopPeriodicProcess.Reset();
ThreadPool.RegisterWaitForSingleObject(stopPeriodicProcess,
(state, timedOut) => DoPeriodicProcess(state, timedOut, e.EngineId), null,
5000, true);
}
Moreover I don't understand why you're doing things this way, can't you use a timer, which is precisely designed for this kind of use-case?

how to implement windows service loop that waits for a period in C# / .NET2.0

My question is that is this the best practice to do this. Couldn't find any good examples. I have following code in file created by VS2005:
public partial class ObjectFolder : ServiceBase
{
protected override void OnStart(string[] args)
{
ObjectFolderApp.Initialize();
ObjectFolderApp.StartMonitorAndWork();
}
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop yourservice.
}
}
then:
class ObjectFolderApp
{
public static bool Initialize()
{
//all init stuff
return true;
}
public static void StartMonitorAndWork()
{
Thread worker = new Thread(MonitorAndWork);
worker.Start();
}
private static void MonitorAndWork()
{
int loopTime = 60000;
if (int.TryParse(_cfgValues.GetConfigValue("OfWaitLoop"), out loopTime))
loopTime = 1000 * loopTime;
while (true)
{
/* create+open connection and fill DataSet */
DataSet ofDataSet = new DataSet("ObjectFolderSet");
using (_cnctn = _dbFactory.CreateConnection())
{
_cnctn.Open();
//do all kinds of database stuff
}
Thread.Sleep(loopTime);
}
}
}
Re-hashing my answer from this question, the recommended way is to use a timer and the following code:
public class MyService : ServiceBase
{
private Timer workTimer; // System.Threading.Timer
protected override void OnStart(string[] args)
{
workTimer = new Timer(new TimerCallback(DoWork), null, 5000, 5000);
base.OnStart(args);
}
protected override void OnStop()
{
workTimer.Dispose();
base.OnStop();
}
private void DoWork(object state)
{
RunScheduledTasks(); // Do some work
}
}
Simple!
Note that the Timer type being used is System.Threading.Timer, same as Justin specifies.
Use a System.Threading.Timer to fire the process off at the scheduled interval.

Categories