I have a Service that hits a database every 10 sec and gets the data if there is any. The thing is that processing this data can take up to 30 sec. If I use a Timer with 10 sec interval the service will get the same data twice.
The effect i´m trying to achieve(Just for visualization):
while(true)
{
if(Getnrofrows() > 0)
do stuff
else
sleep for 10 sec
}
Ppl saying Thread.Sleep is a bad idea in production services, how do I do this with timers?
/mike
Did you try to set Timer property auto reset to false, and enabling timer again when process of refreshing data is over
using System;
public class PortChat
{
public static System.Timers.Timer _timer;
public static void Main()
{
_timer = new System.Timers.Timer();
_timer.AutoReset = false;
_timer.Interval = 100;
_timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
_timer.Enabled = true;
Console.ReadKey();
}
static void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//Do database refresh
_timer.Enabled = true;
}
}
I don't see any problems with using Sleep at all other than you might end up with ugly code.
To answer your question:
public class MyTest
{
System.Threading.Timer _timer;
public MyTest()
{
_timer = new Timer(WorkMethod, 15000, 15000);
}
public void WorkMethod()
{
_timer.Change(Timeout.Infinite, Timeout.Infinite); // suspend timer
// do work
_timer.Change(15000, 15000); //resume
}
}
There is nothing wrong with this approach. A sleeping thread does not consume any CPU cycles.
If you need to do something exactly every X seconds, a timer is the way to go. If, on the other hand, you want to pause for X seconds, then Thread.Sleep is appropriate.
Thread.Sleep is not bad in itself in a service, just that you need to be responsive to service commands, so your worker thread should not go to sleep for an hour, but rather needs to sleep for short periods of time and then wake up and listen if the service controller part of the service is telling it to stop for some reason.
You want to make it so that if the admin tells your service to stop, it'll stop quickly enough so that it won't get any timeout messages where the admin can't be sure that your service is stopped and it's safe to reboot the machine or similar.
Related
I am writing a program that will perform an operation every 10 or 15 minutes. I want it to be running all the time, so I need something that is cheap on processing power. What I have read so far seems to suggest that I want to use a Timer. Here is a clip of the code I have so far.
class Program {
private static Timer timer = new Timer();
static void Main(string[] args) {
timer.Elapsed += new ElapsedEventHandler(DoSomething);
while(true) {
timer.Interval = TimerMilliseconds(); // The duration of the wait will differ each time
timer.Enabled=true;
}
}
}
The problem here is that the while loop just keeps executing rapidly. How do I halt execution until the timer is elapsed. My program really doesn't need to be multi threaded. Is a Timer the right tool for this job?
Thank you in advance for any help!
UPDATE: Sorry for the confusion. I have implemented the DoSomething method. I just did not include it as I don't believe it is part of my issue.
Timer's will fire off the Elapsed event once the specified interval has elapsed.
I would do something like this:
private static Timer timer = new Timer();
static void Main(string[] args)
{
timer.Elapsed += new ElapsedEventHandler(DoSomething);
timer.Interval = TimerMilliseconds(); // The duration of the wait will differ each time
timer.Enabled=true;
Console.ReadKey(); //Wait for keypress to terminate
}
You could also implement this as a service so you don't have to have a blocking call like Console.ReadKey to keep the program from terminating.
Finally, you could just change the interval in the event handler:
static void DoSomething(...)
{
timer.Stop();
timer.Interval = TimerMilliseconds();
...
timer.Start();
}
The problem with this code is that you're using a loop to set the Interval and Enabled properties of the Timer, which will execute said assignments over and over - it's not waiting for the timer to execute in some way.
If your application doesn't need to be mutlithreaded, then you might be better simply calling Thread.Sleep between executions.
class Program {
static void Main(string[] args) {
while(true) {
Thread.sleep(TimerMilliseconds()); // The duration of the wait will differ each time
DoSomething();
}
}
}
take out the timer and loop from your logic. Just use windows scheduler to execute your program after 15 minutes. Or you can use windows services. Please read Best Timer for using in a Windows service
remove the while loop completely.
inside of the DoSomething() function (once implemented) stop timer at start and at the end reset the interval before restarting the timer.
I guess the comments and answrs already provide the hints you need, but the MSDN docs for Timer actually provide a nice example. In my opinion the Timer approach is a bit tidier, it's easier to read your intentions and abstracts away the details of invoking your scheduled code.
Here's another alternative approach using ManualResetEvent and WaitOne(). This will allow you to halt the main thread without worrying about it being killed accidentally by an errant keypress. You can also Set() the MRE when certain conditions are met to allow the app to exit gracefully:
class Program
{
private static Timer timer;
private static ManualResetEvent mre = new ManualResetEvent(false);
static void Main(string[] args)
{
timer = new Timer(TimerCallback, null, 0, (int)TimeSpan.FromMinutes(15).TotalMilliseconds);
mre.WaitOne();
}
private static void TimerCallback(object state)
{
// ... do something in here ...
Console.WriteLine("Something done at " + DateTime.Now.ToString());
}
}
I need a logic that would allow me to do something when a thread is running for more that X amount of seconds.
Like in this incredibly ugly example, here it will check every second and if the workerThread is running for 10 or more minutes it shows a message...
var timeWorking = TimeSpan.FromMinutes(0);
workerThread = new Thread(RunTask);
workerThread.Start(task);
while (workerThread.IsAlive)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
timeWorking = timeWorking.Add(TimeSpan.FromSeconds(1));
if (timeWorking.TotalMinutes < 10) continue;
timeWorking = TimeSpan.FromMinutes(0);
Console.Writeline("Here we go... the event")
}
Please help me to make it right...
What should I use Diagnostics.StopWatch, System.Timers.Timer or Threading.Timer ?
UPD: All the answers confused me even more...
The task is to check if workerThread is running for more than X amount of time, and if it is, call some method, reset the timer and check again if workerThread now is running for more than X amount of time since the last time we called the method... and so on and on...
UPD2: Basically I have a thread that does a processing based on information pulled from AmazonSQS queue. SQS Queue message has a visibility timeout. If the task will take longer than default visibility timeout - the message will be back to the queue before the task has finished. And then it will be picked up by another machine. To avoid that I need to extend visibility timeout of SQS message.
So I can do that by checking periodically if thread stil isALive then I can add couple of minutes to the message visibility timeout. After a minute and 50 seconds or so, I should check again and if thread still isALive then add couple more minutes and so on.
Since you know that the thread needs to do something after ten minutes, why not simply use an interval on the timer like this:
var interval = 1000 * 60 * 10; // ten minutes
var timer = new System.Timers.Timer(interval) { AutoReset = false };
timer.Elapsed += ((sender, eventArgs) =>
{
// Do your work here...
});
workerThread = new Thread(RunTask);
workerThread.Start(task);
timer.Start();
This way you are not checking each second and you will execute your code after a desired amount of time.
I think System.Timers.Timer is better suited based on what you've described. But, it depends. If you want to do something with the UI with the timer. Forms.Timer is better.
In either case, you could simply check if the thread is still alive when the timer Elapsed (or Ticked) and do something if it is.
e.g.
timeThreadStarted = DateTime.Now;
workerThread = new Thread(RunTask);
System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
workerThread.Start(task);
//...
static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if(workerThread != null && workerThread.IsAlive)
{
Console.WriteLine("thread has been running for {0}!", DateTime.Now - timeThreadStarted);
}
}
This checks the thread state after 1 second. If it is still Alive then it has been running for at least one second.
This has the benefit of not blocking any threads. If you have a UI and you want to do this, then you can't block the UI Thread (it will become unresponsive and provide a poor user experience).
You could also do Thread.Join with a TimeSpan like the example at http://msdn.microsoft.com/en-us/library/23f7b1ct.aspx so that you don't have to do a Thread.Sleep.
Note: either approach blocks calling thread until the time has elapsed. Not suitable for main/UI threads.
You can use a Timer that will raise an event once the elapsed time as triggered.
private static void Main(string[] args)
{
var thread = new Thread(
() =>
{
var timer = new System.Timers.Timer
{
Interval = 10000, //10s
AutoReset = false, //only raise the elapsed event once
};
timer.Elapsed += timer_Elapsed;
timer.Start();
while (true)
{
Console.WriteLine("Running...");
Thread.Sleep(1000); //Always put a thread to sleep when its blocking so it does not waste CPU cycles.
}
});
thread.Start();
}
private static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
//thread is running for more that X (10s) amount of seconds
Console.WriteLine("Timer elapsed");
}
That is a simple example. In this example, the thread never exits. But you can add your own logic where necessary to get what you are trying to accomplish.
Short answer: Yes, use System.Timers.Timer
You can use the Task wait method, for example
var t = Task.Factory.StartNew(() => MyAction()); // MyAction is an action to be executed in parallel
bool check = t.Wait(10000); //wait for 10000 milliseconds
if (check)
{
// all ok
}
else
{
// over time
}
The Wait method blocks until the task ends or timeout happens. If you don't want to block your primary thread, you can run the example code using another task that works in parallel and checks the working task.
I've created a watchdog timer (using a System.Windows.Forms.Timer), which triggers if a long period of time expires without receiving a small packet of data:
using System.Windows.Forms;
public class Watchdog
{
private Timer Timer;
public void Go()
{
Timer.Start();
}
public void Reset()
{
Timer.Stop();
Timer.Start();
}
private void OnTimerExpired(object State)
{
Timer.Stop();
DoSomething();
}
public Watchdog()
{
Timer = new Timer();
Timer.Tick += new EventHandler(OnTimerExpired);
Timer.Interval = (1000 * Timeout);
}
}
The main code calls Go(), and then calls Reset() each time a packet is received. If the timer expires, OnTimerExpired() is called.
Since that there may be hundreds of packet receptions per second, and since the main job of the application is to respond to such packets, I'm beginning to wonder if resetting the timer isn't too CPU/OS intensive.
Any idea how calling Timer.Stop()/Timer.Start() this way may impact performance (in terms of latency)?
Use a simple timespan or integer variable as a flag. When the timer ticks, it checks against a Stopwatch object to see how much time has elapsed since the flag was last udpated. If it's longer than your timeout value you trigger your watchdog code.
Now, instead of resetting your timer, other code can just use the stopwatch to update your timespan flag value when a new packet comes in.
You should also either set your timer's tick interval to about 1/2 of what you want the actual timeout duration to be, or have code in the event to set your interval so your next tick event is just a few milliseconds after you would timeout if the connection was severed now. Otherwise you could end up waiting almost twice as long as the timeout duration in the situation where your last packet arrived very soon after a tick event.
Another option, by the way, is to just have a Boolean flag that's set whenever a message comes in. The timer event handler checks that flag and alerts if it's not set. So you have:
private bool GotAMessage = false;
void MessageReceived()
{
// happens whenever a message is received
GotAMessage = true;
}
void OnTimerExpired(object state)
{
if (!GotAMessage)
{
// didn't receive a message in time.
}
GotAMessage = false;
}
A simpler option is to call a method on the WatchDog class that updates a common lastPacketReceived value time a packet is received. Then you only need to start a single timer one time in the WatchDog class that ticks once per timeout interval and compares the current time to the lastPacketReceived value:
public static class WatchDog
{
static object locker = new object();
static long lastPacketReceived;
static Stopwatch stopWatch = new Stopwatch();
static long threshold = 5000;
static WatchDog()
{
Timer watchDogTimer = new Timer(1000);
watchDogTimer.Elapsed += new ElapsedEventHandler(watchDogTimer_Elapsed);
watchDogTimer.Start();
stopWatch.Start();
}
static void watchDogTimer_Elapsed(object sender, ElapsedEventArgs e)
{
lock (locker)
{
if ((stopWatch.ElapsedMilliseconds - lastPacketReceived) > threshold)
{
// threshold exceeded
}
}
}
public static void PacketReceived()
{
lock (locker)
{
lastPacketReceived = stopWatch.ElapsedMilliseconds;
}
}
}
Any idea how calling Timer.Stop()/Timer.Start()
This way may impact performance (in terms of latency)?
None
The amount of resources required to do this is unlikely to be measured. Unless you have a performance problem, don't try to solve a performance problem, at the very least use software to profile the software to see if its an actual problem.
During debugging I can see that after Timer.Stop() or Timer.Enabled = false commands are executed, Timer is still running (Timer.Enabled = true). How is that possible?
This is possible when you stop the timer on a worker thread. For example:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
Timer timer1;
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
timer1 = new Timer();
timer1.Interval = 3000;
timer1.Start();
var t = new System.Threading.Thread(stopTimer);
t.Start();
}
private void stopTimer() {
timer1.Enabled = false;
System.Diagnostics.Debug.WriteLine(timer1.Enabled.ToString());
}
}
Output:
True
The timer must be stopped by the UI thread, the class takes care of it automatically. Quite similar to Control.BeginInvoke(). There's an explicit race, the Tick event handler can run after you stopped it. This can also happen on the UI thread if the very first timer you create is created on a worker thread. A splash screen for example. That's not healthy, you ought to fix that.
Calling Start after you have disabled a Timer by calling Stop will cause the Timer to restart the interrupted interval. If your Timer is set for a 5000-millisecond interval, and you call Stop at around 3000 milliseconds, calling Start will cause the Timer to wait 5000 milliseconds before raising the Tick event.
bear also in mind
Calling Stop on any Timer within a Windows Forms application can cause messages from other Timer components in the application to be processed immediately, because all Timer components operate on the main application thread. If you have two Timer components, one set to 700 milliseconds and one set to 500 milliseconds, and you call Stop on the first Timer, your application may receive an event callback for the second component first. If this proves problematic, consider using the Timer class in the System.Threading namespace instead.
http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.stop.aspx
public void EnableTimer(bool state)
{
if (this.InvokeRequired) {
this.Invoke(new Action<bool>(EnableTimer), state);
} else {
this.Timer1.Enabled = state;
}
}
Try this code...
I created a windows service, that is supposed to check a certain table in the db for new rows every 60 seconds. For every new row that was added, I need to do some heavy processing on the server that could sometimes take more than 60 seconds.
I created a Timer object in my service, that ticks every 60 seconds and invokes the wanted method.
Since I don't want this timer to tick while processing the new lines found, I wrapped the method in a lock { } block, so this won't be accessible by another thread.
It looks something like this :
Timer serviceTimer = new Timer();
serviceTimer.Interval = 60;
serviceTimer.Elapsed += new ElapsedEventHandler(serviceTimer_Elapsed);
serviceTimer.Start();
void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
lock (this)
{
// do some heavy processing...
}
}
Now, I'm wondering -
If my timer ticks, and finds a lot of new rows on the db, and now the processing will take more than 60 seconds, the next tick won't do any processing till the previous one finished. This is the effect I want.
But now, will the serviceTimer_Elapsed method go off immediatly once the first processing was finished, or will it wait for the timer to tick again.
What I want to happen is - if the processing requires more than 60 seconds, than the timer will notice the thread is locked, and wait another 60 seconds to check again so I will never get stuck in a situation where there are a queue of threads waiting for the previous one to finish.
How can i accomplish this result ?
What is the best practice for doing this ?
Thanks!
You might try disabling the timer during processing, something like
// Just in case someone wants to inherit your class and lock it as well ...
private static object _padlock = new object();
try
{
serviceTimer.Stop();
lock (_padlock)
{
// do some heavy processing...
}
}
finally
{
serviceTimer.Start();
}
Edit : OP didn't specify whether the reentrancy was caused only by the timer or whether the service was multi threaded. Have assumed the later, but if the former then locking should be unnecessary if the timer is stopped (AutoReset or manually)
You don't need the lock in this case. Set timer.AutoReset=false before starting it.
Restart the timer in the handler after you are done with your processing. This will ensure that the timer fires 60 seconds after each task.
A similar variation on other answers, that allows the timer to keep ticking and only do the work when the lock can be obtained, instead of stopping the timer.
Put this in the elapsed event handler:
if (Monitor.TryEnter(locker)
{
try
{
// Do your work here.
}
finally
{
Monitor.Exit(locker);
}
}
Put a quick check it see if the service is running. if it is running it will skip this event and wait for the next one to fire.
Timer serviceTimer = new Timer();
serviceTimer.Interval = 60;
serviceTimer.Elapsed += new ElapsedEventHandler(serviceTimer_Elapsed);
serviceTimer.Start();
bool isRunning = false;
void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
lock (this)
{
if(isRunning)
return;
isRunning = true;
}
try
{
// do some heavy processing...
}
finally
{
isRunning = false;
}
}
I recommend you don't let the timer tick at all while its processing.
Set the Timers AutoReset to false. And start it at the end. Here's a full answer you might be interested in
Needed: A Windows Service That Executes Jobs from a Job Queue in a DB; Wanted: Example Code
Other options might be to use a BackGroundWorker class, or TheadPool.QueueUserWorkItem.
Background worker would easily give you the option check for current processing still occurring and process 1 item at a time. The ThreadPool will give you the ability to continue queueing items every tick (if necessary) to background threads.
From your description, I assume you are checking for items in a queue in a database. In this case, I would use the ThreadPool to push the work to the background, and not slow/stop your checking mechanism.
For a Service, I would really suggest you look at using the ThreadPool approach. This way, you can check for new items every 60 seconds with your timer, then Queue them up, and let .Net figure out how much to allocate to each item, and just keep pushing the items into the queue.
For Example: If you just use a timer and you have 5 new rows, which require 65 seconds of processing time total. Using the ThreadPool approach, this would be done in 65 seconds, with 5 background work items. Using the Timer approach, this will take 4+ minutes (the minute you will wait between each row), plus this may cause a back-log of other work that is queueing up.
Here is an example of how this should be done:
Timer serviceTimer = new Timer();
void startTimer()
{
serviceTimer.Interval = 60;
serviceTimer.Elapsed += new ElapsedEventHandler(serviceTimer_Elapsed);
serviceTimer.AutoReset = false;
serviceTimer.Start();
}
void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
// Get your rows of queued work requests
// Now Push Each Row to Background Thread Processing
foreach (Row aRow in RowsOfRequests)
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(longWorkingCode),
aRow);
}
}
finally
{
// Wait Another 60 Seconds and check again
serviceTimer.Stop();
}
}
void longWorkingCode(object workObject)
{
Row workRow = workObject as Row;
if (workRow == null)
return;
// Do your Long work here on workRow
}
There's quite a neat way of solving this with Reactive Extensions. Here's the code, and you can read a fuller explanation here: http://www.zerobugbuild.com/?p=259
public static IDisposable ScheduleRecurringAction(
this IScheduler scheduler,
TimeSpan interval,
Action action)
{
return scheduler.Schedule(
interval, scheduleNext =>
{
action();
scheduleNext(interval);
});
}
And you could use it like this:
TimeSpan interval = TimeSpan.FromSeconds(5);
Action work = () => Console.WriteLine("Doing some work...");
var schedule = Scheduler.Default.ScheduleRecurringAction(interval, work);
Console.WriteLine("Press return to stop.");
Console.ReadLine();
schedule.Dispose();
another posibility would be something like this:
void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (System.Threading.Monitor.IsLocked(yourLockingObject))
return;
else
lock (yourLockingObject)
// your logic
;
}