I'm currently building a Windows Service which needs to process a queue of messages that are sat in a database table. This queue could vary in length and could take anything from 5 seconds to 55 seconds to execute against all rows in the database (I'm currently using a test data set of 500,000 records)
The Windows Service is configured to run on a 30 second timer so I have tried, unsuccessfully, to ensure that when the timer delegate runs that it is not able to run again until the previous request to the method has completed successfully
I have the following code in my Windows Service OnStart method:
AutoResetEvent autoEvent = new AutoResetEvent(false);
TimerCallback timerDelegate = new TimerCallback(MessageQueue.ProcessQueue);
Timer stateTimer = new Timer(timerDelegate, autoEvent, 1000, Settings.Default.TimerInterval); // TimerInterval is 30000
autoEvent.WaitOne();
And the following code in MessageQueue.ProcessMessage:
Trace.Write("Starting ProcessQueue");
SmtpClient smtp = new SmtpClient("winprev-01");
AutoResetEvent autoEvent = (AutoResetEvent)stateObject;
foreach (MessageQueue message in AllUnprocessed)
{
switch (message.MessageType)
{
case MessageType.PlainText:
case MessageType.HTML:
SendEmail(smtp, message);
break;
case MessageType.SMS:
SendSms(message);
break;
default:
break;
}
}
autoEvent.Set();
Trace.Write("Ending ProcessQueue");
I'm using DebugView to analyse the view the Trace statements as the Service runs and I can see multiple instances of "Starting ProcessQueue" which occur every 30 seconds which is what I am trying to avoid happening
In summary: I want to call ProcessQueue and ensure that it is not executed again unless it has completed its work (this enables me to prevent the same messages in the queue being processed multiple times
I'm sure I'm missing something pretty obvious here so any help would be much appreciated :)
Dave
Why don't you have your delegate disable the timer and then re-enable it (or continue working, if timer would expire immediately) once it's through working. Provided the latency between timer firing and your delegate waking up is < 30 seconds, this should be watertight.
while (true)
{
Trace.Write("Starting ProcessQueue")
stateTimer.Enabled = false;
DateTime start = DateTime.Now;
// do the work
// check if timer should be restarted, and for how long
TimeSpan workTime = DateTime.Now - start;
double seconds = workTime.TotalSeconds;
if (seconds > 30)
{
// do the work again
continue;
}
else
{
// Restart timer to pop at the appropriate time from now
stateTimer.Interval = 30 - seconds;
stateTimer.Enabled = true;
break;
}
}
Your ProcessMessage is never checking if the resetEvent is signaled - it's just running regardless.
I post here how to fix this. However, this is not the ideal method to do what you want to do. See the bottom of my answer for that.
You have your call to autoEvent.WaitOne() in the wrong place; it should be at the beginning of the ProcessMessage method.
AutoResetEvent autoEvent = (AutoResetEvent)stateObject;
autoEvent.WaitOne();
Trace.Write("Starting ProcessQueue");
SmtpClient smtp = new SmtpClient("winprev-01");
foreach (MessageQueue message in AllUnprocessed){
You should also use the overload that accepts a time out value (int or timespan), and returns a bool If the method returns true, that means it was signaled, so you can continue. If it times out (because another iteration is still running), you should just return and not try to run the code again.
If you do not use such an overload, what you are doing would be no different than wrapping the ProcessMessage method's code in a critical section (lock() on a global var, for instance) - additional threads would block, and then needlessly run.
AutoResetEvent autoEvent = (AutoResetEvent)stateObject;
//wait just one ms to see if it gets signaled; returns false if not
if(autoEvent.WaitOne(1)){
Trace.Write("Starting ProcessQueue");
SmtpClient smtp = new SmtpClient("winprev-01");
foreach (MessageQueue message in AllUnprocessed){
Note that actually, a *ResetEvent isn't ideal here. You really just want to check if an instance is already running, and abort if so. ResetEvents aren't really made for that... but I wanted to address the question of using the ResetEvent anyway.
What would probably work better is to simply shut down the timer when the callback is called, and then restart it up when you are done. That way, it's impossible for that code to be re-entered while it's still running.
You absolutely would need to wrap all the code in the callback method in a try / finally though, so that you always restart the timer after.
You can trivially solve this by using a System.Threading.Timer. You make it a one-shot timer by setting its period to zero. Restart the timer in the callback. Overlapped execution of the callback is now impossible.
Since you run this so frequently, a different approach is to use a thread instead. You'll need an AutoResetEvent to signal the thread to stop in the OnStop() method. Its WaitOne() method gives you a free timer when you use the overload that takes the millisecondsTimeout argument.
Btw: note that the autoEvent.WaitOne() call in OnStart() is troublesome. It may timeout the service controller if the first email takes a long time to send. Just omit it, you got the timer started == service started.
I think you are making this a lot harder than it needs to be. Why not just create a separate thread that spins around an infinite loop calling MessageQueue.ProcessQueue and then waiting a certain amount of time before calling it again. If it is all happening on a single thread there is no way for anything to happen in parallel.
public class YourService : ServiceBase
{
private ManualResetEvent m_Stop = new ManualResetEvent(false);
protected override void OnStart(string[] args)
{
new Thread(Run).Start();
}
protected override void OnStop()
{
m_Stop.Set();
}
private void Run()
{
while (!m_Stop.WaitOne(TimeSpan.FromSeconds(30))
{
MessageQueue.ProcessMessage();
}
}
}
OnStart method
AutoResetEvent autoEvent = new AutoResetEvent(true);
while (true)
{
autoEvent.WaitOne();
Thread t = new Thread(MessageQueue.ProcessMessage);
t.Start(autoEvent);
}
What you want is a synchronization timer object. In Win32 this is known as a waitable timer (unfortunately some P/invoke is required, unless I'm mistaken).
Here's what you would do:
Create waitable timer (make sure it's auto-reset).
Set waitable timer with a period of 30 seconds.
Loop:
WaitForSingleObject(waitable timer) with infinite timeout.
Process queue.
If the processing takes more than 30s, the timer will simply remain set until you call WaitForSingleObject on it. Additionally, if the processing takes 20s for example, the timer will be signaled after 10 more seconds.
Related
I write a Windows Service in .Net Framework 4.0 and I need to schedule a recurring task inside. New task can only run if previous one is finished, so no tasks in parallel...
All my task occurences work on same object (WCF Channel factory).
A task takes almost 2 seconds to complete and may be scheduled every 2 seconds or every hour.
My constraint is to have this Windows service as invisible/light as possible on memory and processor uses point of view...
I've already found these 2 ways:
Use a System.Timers.Timer with Autoreset to false => I've to
implement an ElapsedEventHandler and pass my shared object (WCF
Channel factory)
Use a never ending loop: not sure of mem/proc use in
that state but no threads aspect to take care of.
Any suggestions?
Thanks and have a nice day!
For me was fine following: I'm started timer once, then in Tick method I will schedule next Tick call. Like this:
private Timer _timer;
//Interval in milliseconds
int _interval = 1000;
public void SetTimer()
{
// this is System.Threading.Timer, of course
_timer = new Timer(Tick, null, _interval, Timeout.Infinite);
}
private void Tick(object state)
{
try
{
// Put your code in here
}
finally
{
_timer?.Change(_interval, Timeout.Infinite);
}
}
// dont forget to dispose your timer using await _timer.DisposeAsync(); or _timer.Dispose();
System.Timers.Timer is the way to go and will have little to no system performance impact. Current systems can handle thousands of timers.
Since you want the timer to continue, don't set AutoReset, but you will need a way to change its interval (if that's what you need).
Your service instance should hold an instance of your WCF channel factory.
To ensure synchronous processing, you should implement an Interlocked protected flag, like a long, which can serve as an indicator of busyness. If equal to one, for example, the method that kicks off processing from timer elapsed event will simply return. Once processing is complete, at which time you set the flag to zero, further timer elapsed events will be able to enter and kick off processing again.
Remember to stop, restart, and dispose of your timer in the various service events, like pause, stop, start.
I have a function that needs to archive 90 day old emails every midnight. I created a class to handle this and here's the example:
public void processArchives()
{
initializeTimer();
}
private void initializeTimer()
{
var now = DateTime.Now;
var tomorrow = now.AddDays(1);
var durationUntilMidnight = tomorrow.Date - now;
var t = new Timer(o => { attemptArchivalProcess(); }, null, TimeSpan.Zero, durationUntilMidnight);
}
private void attemptArchivalProcess()
{
//perform archival
initializeTimer(); //re-start timer to process tomorrow
}
question is, will the repeated calls to initializeTimer cause a stack overflow (repeated function calls) or will it run fine 'forever'?
and should I be able to call processArchives() as a new thread, and keep the thread open or do I need some sort of loop after the init call something like:
while(!Program.Closing){ sleep(...); }
to keep it from being garbage collected?
I think you are close to your potential solution.
Timer
To answer your first question: As you already concluded the timer will elapse on it's delegate. The delegate will be executed on a separate thread and each timer elapse will get a brand new fresh own stack to execute on. Thus, endless timer elapsed events will never trigger a StackOverflowException.
Wait until forever?
An attempt to answer your second question: You don't have to write an endless loop to keep your application alive. But, you could do that, it all depends on what you need for your application. Weigh the pros and cons.
Luckily there are more solutions possible (there is no right or wrong, weigh them out to fulfill your needs)
A shot list of solutions you could concider:
Console.ReadLine()
If you have a console application, you could simply wait for user input. The main thread will wait forever without consuming processor power.
As suggested by Servy, create a scheduled task
That way you don't have to do anything at all to write endless loops. Your application will simply exit when it's done. Might not be the most handsome solution if you actually deploy this app to users.
Windows service
You could also go for a bit more mature solution and write a windows service (sounds more complicated than it is, it's pretty simple to write a basic windows service). That way you also don't have to bother about writing never ending loops, a windows service will run forever by design (unit you decide to stop it of course)
Alternative for never ending while loop - WaitHandle
You could also use a signal mechanism (e.g. with a AutoResetEvent) so that your main thread can Wait until a certain signal is set. That way you also don't have to actively wait (=not consume processor cycles).
You have tons of alternatives, it all boils down to your specific needs, which I can't decide for you. You can. :)
All those words, let's throw in an example. The unit test represents your application. The timer is a different type, namely the System.Timers.Timer. You can set that timer to AutoReset so that you don't have to create new timers.
Here the example, I hope it makes sense to you (if not, comment, maybe I can clarify)
private Timer _processTimer;
private AutoResetEvent _resetSignal;
[Test]
public void YourImaginaryMainApp()
{
const int interval = 24 * 60 * 60 * 1000; // every day
_resetSignal = new AutoResetEvent(false);
_processTimer = new Timer(interval)
{
AutoReset = true
};
_processTimer.Elapsed += ProcessTimerOnElapsed;
_resetSignal.WaitOne( /*infinite*/);
}
Edit x1 - meant "heap", not "stack" in second sentence... (d'oh!)
I don't think this will cause a stack overflow for a very simple reason. The line var t = new Timer(... creates a new object on the heap. The function pointer is kept internally within the object and should (in theory) never be added to the stack until it's actually called. When attemptArchivalProcess() is called, it in turns calls initializeTimer() (adding to the stack) but this then completes and exits as normal on the same thread (removing from the stack). When the Timer does kick in, it'll start off that 2-call entry to the stack.
Now, all this said, I know there is increased complexity going on under the hood with the stack but my point is that ultimately that you have 2 methods being called which then exit correctly - and should be cleaned up correctly when they exit.
Or at least that's my reasoning. I fully admit I'm open to correction on this though...
Here's my attempted resolution for this....
System.Threading.Timer timerFunc = null;
public void processArchives()
{
initializeTimer();
while (!CSEmailQueues.StoppingService) //is
Thread.Sleep(CSEmailQueues.sleeptime);
timerFunc.Dispose();
return;
}
private void initializeTimer()
{
var now = DateTime.Now;
var tomorrow = now.AddDays(1);
var durationUntilMidnight = tomorrow.Date - now;
if (timerFunc != null) timerFunc.Dispose();
timerFunc = new System.Threading.Timer(o => { attemptArchivalProcess(); }, null, TimeSpan.Zero, durationUntilMidnight);
}
private void attemptArchivalProcess()
{
//Do Work
initializeTimer(); //re-start timer to process tomorrow
}
So...this will dispose the timer object and create a new one each time it runs (as this timer only executes once). Plus being a class level variable, there is always a reference to the timer so the garbage collector doesn't dispose of it while i'm waiting for it to trigger.
Then all I have to do is create a thread that calls processArchives() from the onStart call for the service, and this should in essence run forever unless the onStop is called and sets StoppingService to true.
Also I am guessing I shouldn't have to worry about cross-thread use of timerFunc by the timer callback as there should never be more than 1 instance at any given time to access this object.
I am going to create a system service in C#.
In the onstart section I would like to loop every 30 seconds and query a mysql database. If numrows are greater than 0 I will process some faxes using the faxcom library.
My question is: Would looping every 30 seconds exhaust the program/computer? What would be the best function/method to use for the loop and sleep? Do you have any example code for the loop and sleep?
Using Thread.Sleep() would be a bad solution, because even while sleeping your thread is active. Use Timer class instead and handle its Elapsed event.
This article examines different ways to tackle the periodical execution of your service.
Here is what your OnStart method might look like:
using System.Timers;
private timer = new Timer();
protected override void OnStart(string[] args)
{
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 30000; // every 30 seconds
timer.Enabled = true;
}
Private void OnElapsedTime(object source, ElapsedEventArgs e)
{
// Execute your code here
}
I wouldn't use looping constructs for such a thing.
I would use one of the timer controls in the BCL and set it to fire every 30 seconds.
As for the question of if this is "too much", the answer entirely depends on the amount of work being done and the load it generates.
No, you would not be using the CPU, because sleeping threads are not scheduled for execution until their sleep time expires. Use Thread.Sleep to make the current thread sleep for timeout miliseconds. Something like:
while(!stop) // boolean variable to indicate when to stop the service.
{
Thread.Sleep(30000);
// do work
}
You will, of course, need to run this on a separate thread, otherwise you will block the main thread.
I would avoid using System.Timers.Timer in your case solely because you are writing a Windows Service. While you can use it, you won't have a GUI available and therefore don't need anything that this timer would expose as if you were using a GUI (it inherits from System.ComponentModel.Component for this reason). It's pretty simple
to use.
I have requirement to cancel method execution if it takes the more than two seconds to complete and restart it on another thread.
So, is there any way/call back mechanism/HACK, I can make method inform me that it crossed 2 seconds time limit?
check if network drive exists with timeout in c#
https://web.archive.org/web/20140222210133/http://kossovsky.net/index.php/2009/07/csharp-how-to-limit-method-execution-time
Async Pattern:
public static T SafeLimex<T>(Func<T> F, int Timeout, out bool Completed)
{
var iar = F.BeginInvoke(null, new object());
if (iar.AsyncWaitHandle.WaitOne(Timeout))
{
Completed = true;
return F.EndInvoke(iar);
}
F.EndInvoke(iar); //not calling EndInvoke will result in a memory leak
Completed = false;
return default(T);
}
You should create System.Threading.Timer on two seconds, and run your method in another thread and wait for callback from it, if method completes before timer runs you should dispose timer, otherwise you should abort thread in which you method are executing. This is pretty simple for example
using (new Timer(BreakFunction, true, TimeSpan.FromMinutes(2), Timeout.Infinite))
{
//TODO:here you should create another thread that will run your method
}
In BreakFunction you should abort thread that runs your methods
It would be good if you can find it. I've been looking for it too.
What I usually do is start the method in another Thread, and start a Timer with 2 seconds in this case. The first time it raises the event, just do:
if (a.IsAlive)
{
a.Abort();
}
Two important things:
The Thread declared should be visible by the method that handles the timer
When calling Abort(), it raises ThreadAbortException, so you should correctly handle it in the method.
I am running a windows service and using a loop and Thread.Sleep to repeat a task, would it be better to use a timer method?
If yes a code example would be great
I am currently using this code to repeat
int curMinute;
int lastMinute = DateTime.Now.AddMinutes(-1).Minute;
while (condition)
{
curMinute = DateTime.Now.Minute;
if (lastMinute < curMinute) {
// do your once-per-minute code here
lastMinute = curMinute;
}
Thread.Sleep(50000); // sleeps for 50 seconds
if (error condition that would break you out of this) {
break; // leaves looping structure
}
}
A timer is a better idea, IMO. That way, if your service is asked to stop, it can respond to that very quickly, and just not call the timer tick handler again... if you're sleeping, the service manager will either have to wait 50 seconds or kill your thread, neither of which is terribly nice.
class Program
{
static void Main(string[] args)
{
Timer timer = new Timer(new TimerCallback(TimeCallBack),null,1000,50000);
Console.Read();
timer.Dispose();
}
public static void TimeCallBack(object o)
{
curMinute = DateTime.Now.Minute;
if (lastMinute < curMinute) {
// do your once-per-minute code here
lastMinute = curMinute;
}
}
The code could resemble something like the one above
It's important to understand that your code will sleep for 50 seconds between ending one loop, and starting the next...
A timer will call your loop every 50 seconds, which isn't exactly the same.
They're both valid, but a timer is probably what you're looking for here.
Beware that calling Sleep() will freeze the service, so if the service is requested to stop, it won't react for the duration of the Sleep() call.
Yes, using a Timer will free up a Thread that is currently spending most of its time sleeping. A Timer will also more accurately fire every minute so you probably won't need to keep track of lastMinute anymore.
Not quite answering the question, but rather than having
if (error condition that would break you out of this) {
break; // leaves looping structure
}
You should probably have
while(condition && !error_condition)
Also, I'd go with a Timer.
I have used both timers and Thread.Sleep(x), or either, depending on the situation.
If I have a short piece of code that needs to run repeadedly, I probably use a timer.
If I have a piece of code that might take longer to run than the delay timer (such as retrieving files from a remote server via FTP, where I don't control or know the network delay or file sizes / count), I will wait for a fixed period of time between cycles.
Both are valid, but as pointed out earlier they do different things. The timer runs your code every x milliseconds, even if the previous instance hasn't finished. The Thread.Sleep(x) waits for a period of time after completing each iteration, so the total delay per loop will always be longer (perhaps not by much) than the sleep period.
I required a thread to fire once every minute (see question here) and I've now used a DispatchTimer based on the answers I received.
The answers provide some references which you might find useful.
I agree as well, using a timer is the best option. I have tried a solution similar to yours in the past and started having issues where the loop would misfire, and I would have to wait for another Thread.Sleep() before it would fire again. Also, it did cause all sorts of issues with stopping the service, I would get constant errors about how it wasn't responding and had to be closed.
#Prashanth's code should be exactly what you need.
You can use either one. But I think Sleep() is easy, clear and shorter to implement.
I would have to say a sleep is a better implementation with a state machine behind it. This would still keep you in control of the application at all times, but allowing any response needed at any specific time. This also will handle timer callbacks that are shorter than the "Processing execution time in the loop"
For example..
<!-- language: c# -->
public enum State
{
Idle = 0,
Processing = 1,
Stop = 100,
}
public void Run()
{
State state = State.Idle; // could be a member variable, so a service could stop this too
double intervalInSeconds = 60;
System.DateTime nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds);
while (state != State.Stop)
{
switch (state)
{
case State.Idle:
{
if (nextExecution > System.DateTime.Now)
{
state = State.Processing;
}
}
break;
case State.Processing:
{
// do your once-per-minute code here
// if you want it to stop, just set it state to stop.
// if this was a service, you could stop execution by setting state to stop, also
// only time it would not stop is if it was waiting for the process to finish, which you can handle in other ways
state = State.Idle;
nextExecution = System.DateTime.Now.AddSeconds(intervalInSeconds);
}
break;
default:
break;
}
System.Threading.Thread.Sleep(1);
}
}