Executing a Function at a Specific time - c#

I have a timer running in my app which I want to stop and start according to local time.
So I need something like this:
if ( time = 08:00) {StartTimer();}
If ( time = 18:00) {StopTimer();} //This can be done from the timer event itself
Is there a way to do this without using another timer?
I can stop the timer from within the timer event itself, but how will i start it again?

You can set the timer's interval to 14 hours instead of stopping it or keep it running with short interval and checking additional condition (the time of the day) internally.

You can try this:-
1) Create a console app that does what you're looking for.
2) Use the Windows "Scheduled Tasks" functionality to have that console app executed at the time you need it to run
or
You can also look at this example:-
using System;
using System.Threading;
public class TimerExample {
// The method that is executed when the timer expires. Displays
// a message to the console.
private static void TimerHandler(object state) {
Console.WriteLine("{0} : {1}",
DateTime.Now.ToString("HH:mm:ss.ffff"), state);
}
public static void Main() {
// Create a new TimerCallback delegate instance that
// references the static TimerHandler method. TimerHandler
// will be called when the timer expires.
TimerCallback handler = new TimerCallback(TimerHandler);
// Create the state object that is passed to the TimerHandler
// method when it is triggered. In this case a message to display.
string state = "Timer expired.";
Console.WriteLine("{0} : Creating Timer.",
DateTime.Now.ToString("HH:mm:ss.ffff"));
// Create a Timer that fires first after 2 seconds and then every
// second.
using (Timer timer = new Timer(handler, state, 2000, 1000)) {
int period;
// Read the new timer interval from the console until the
// user enters 0 (zero). Invalid values use a default value
// of 0, which will stop the example.
do {
try {
period = Int32.Parse(Console.ReadLine());
} catch {
period = 0;
}
// Change the timer to fire using the new interval starting
// immediately.
if (period > 0) timer.Change(0, period);
} while (period > 0);
}
// Wait to continue.
Console.WriteLine("Main method complete. Press Enter.");
Console.ReadLine();
}
}

You could create a thread that ticks every second.
There you can check if you want to start or stop your timer.
Read the folowing: Threads.
In your thread add something like:
if (CurrentTime == "08:00")
StartTimer();
else if if (CurrentTime == "18:00")
StopTimer();
Thread.Sleep(1000); // Makes the Thread Sleep 1 Second

Since you need at least one timer running always (to detect when it's 8 in the morning) then you could simply have just a single timer that runs all day.
Whenever the timer ticks, check the time. If it isn't between 0800 and 1800 just return without doing anything and wait for the next tick.
You could try increasing the timer interval to a value that gets you to e.g. 17:55 and then decrease it again, but there will not be any measurable performance difference so IMHO this is work for no benefit.

Related

How to reset an incrementing counter every N minutes

I have a counter in my program that I want to reset to 0 every 10 minutes.
My program is expected to raises events. These events correspond to warnings due to heavy usage of resources or going out of the test scenarios in our experiments, which would require some action such as dumping some test-related data in the form of CSV and some plots in Tiff format. Tiff files will be produced every 1 minute when the event counter reaches 3.
But due to large size of Tiff files I wish not to over-produce these files. Hence, reseting the counter would ensure that only re-occurring events are followed for further action.
Without adding too much unnecessary details, the main structure of my program is as below:
class Program
{
static void Main(string[] args)
{
counter = 0;
using (an API)
{
// do something here, which may raise an event
while (event)
{
// take an action
counter++; // keeps track of events raised
}
if (counter > 3)
{
// take a specific action
}
else
{
// take action B
}
counter = 0; // reset counter every 10 minutes, by calling a timer or async method
// to keep the application going
System.Windows.Forms.Application.Run();
}
}
// a timer method() // to help me reset the counter
// or
// an Async method ResetCounter()
}
I have attempted to start a timer by creating a timer method:
private static bool TimeCounter()
{
System.Timers.Timer _delayTimer = new System.Timers.Timer();
_delayTimer.Interval = 100000;
_delayTimer.Enabled = true;
// _delayTimer.Elapsed += new ElapsedEventHandler(_delayTimer_Elapsed); // attempted to use an additional method as well that could get triggered after 10 mins but it gets too complicated
_delayTimer.Start();
// not sure how to set this timer to return a boolean true when time elapsed, rather than calling another method
_delayTimer.AutoReset = autoreset;
}
private static void _delayTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
ResetCounter(); // the method not created yet
}
But taking the timer approach, firstly, I am not sure how to get this timer to return a boolean true when the time elapses,
secondly, if my API in the main method calls this method every time the program gets past the if-else conditional this may reset the timer again without ever letting the first 10 minutes timer elapse.
So coming across async-await I feel this could be a better option for me, I could may be call something like this (seen here on Stackoverflow) for resetting the counter?:
var result = Task.Run(async () => { return await myAsyncMethod(); }).Result;
I have never worked with async-await before so not sure how I could achieve the desired outcome with async-await.
I would simply work with DateTime.Now
1) Save the current time whenever you reset the timer or when the code will be executed first time:
var lastReset = DateTime.Now;
2) Check if the lastReset is 10 Minutes or more ago:
if(lastReset.AddMinutes(10) <= DateTime.Now)
{
counter = 0;
}
If you want your counter to be reset as soon as 10 minutes have passed, regardless of what else happens to be going on at that moment, then you can keep going with your System.Timers.Timer idea. Your comments to the question suggest that this is what you want.
To make something happen when a Timer expires, you attach an event handler for the Elapsed event. I suggest using lambda expressions to create the handler as an anonymous function, like this:
_delayTimer.Elapsed += (o,e) => { counter = 0; };
Since this code references counter it needs to be in a location where counter is available. (The new ElapsedEventHandler part is unnecessary -- the compiler will automatically create the delegate for you since you're attaching to an event.)
With object initializer syntax to make your code neater, creating and configuring the Timer becomes this:
var delayTimer = new System.Timers.Timer
{
Interval = 600000, // 10 minutes is 10 * 60 * 1000 == 600000 ms
AutoReset = true, // makes the timer start over automatically
};
delayTimer.Elapsed += ((o, e) => { counter = 0; });
delayTimer.Start();
Note that there's no need to explicitly set Timer's Enabled property, because the Start() method will do this for you.
Side note: A cool thing about this is that it actually doesn't matter where counter is declared (as long as it's available when the handler is created). This construct where an anonymous function references an "outside" variable results in what's called a "closure" over counter. In C#, closures make variables "shared", so that the function can access the variable even if the function is invoked from a place outside of the scope where the variable was declared. In other words, this will work even if counter is a local variable (that might be impractical for other reasons, though).
Full example (console app)
using System;
using System.Timers;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
// Declare the counter somewhere
var counter = 0;
// Create timer
var delayTimer = new Timer
{
Interval = 5000, // Changed to 5 seconds for demo purposes
AutoReset = true,
};
// Create the event handler
delayTimer.Elapsed += ((o, e) =>
{
// Print counter value before resetting
Console.WriteLine($"[Timer elapsed] The counter has value {counter}, resetting it...");
counter = 0;
});
// Start the timer
delayTimer.Start();
// Now simulate doing other stuff while the timer is running...
Console.WriteLine("I'll be silently incrementing the counter at a random pace.");
Console.WriteLine("Every five seconds, the timer event handler will reset the counter " +
"right after telling you how far I got.");
var r = new Random();
while (true)
{
// Sleep for a random number of milliseconds (between 0 and 999)
var sleepLength = r.Next() % 1000;
System.Threading.Thread.Sleep(sleepLength);
// Increment the counter
counter++;
}
// Console output example (values will be random):
// I'll be silently incrementing the counter at a random pace.
// Every five seconds, the timer event handler will reset the counter right after telling you how far I got.
// [Timer elapsed] The counter has value 11, resetting it...
// [Timer elapsed] The counter has value 9, resetting it...
// [Timer elapsed] The counter has value 12, resetting it...
// [Timer elapsed] The counter has value 10, resetting it...
// [Timer elapsed] The counter has value 9, resetting it...
// [Timer elapsed] The counter has value 8, resetting it...
// [Timer elapsed] The counter has value 6, resetting it...
// [Timer elapsed] The counter has value 4, resetting it...
// [Timer elapsed] The counter has value 14, resetting it...
}
}
}
An alternative solution is use Thread.Timer, If you need exact interval use the logic suggested by #speschel
static int counter = 0;
static void Main(string[] args)
{
Timer timer = new Timer(ResetCount, null, 0, 100000);
while (true)
{
//Event simulation
if (Console.ReadKey().Key == ConsoleKey.Enter)
{
Console.WriteLine("Event triggerd"); ;
counter++;
}
if (counter > 3)
{
Console.WriteLine("Take a specific action");
}
else
{
Console.WriteLine("Take action B");
}
Thread.Sleep(1000);
}
}
private static void ResetCount(object state)
{
counter = 0;
}
The real question is in the comments :
These events correspond to warnings due to heavy usage of resources or going out of the test scenarios in our experiments, which would require some action such as dumping some test-related data in the form of CSV and some plots in Tiff format. Tiff files will be produced every 1 minute when the event counter reaches 3.
But due to large size of Tiff files I wish not to over-produce these files. Hence, reseting the counter would ensure that only re-occurring events are followed for further action.
Processing event streams is the realm of Reactive Extensions, available as a NuGet package. Rx works with streams of events the same way LINQ deals with data.
Assuming we have a source of events, one could execute an action if there are more than 10 warnings per 3 minutes with this code :
var warnings = eventSource
.Where(evt => evt.Level >= Level.Warning)
.Buffer(TimeSpan.FromMinutes(3))
.Where(evts => evts.Count > 10)
.Subscribe(evts => ProcessEvents(evts));
Buffer batches events in 3 minute windows. Where() filters events just like LINQ's Where would and only allows events whose level is warning or above. Later on, it only allows batches that have more than 10 warnings.
The end result is that ProcessEvents is called only if there are more than 10 warnings in a 3 minute window.
The source is any class that implements IObservable. Events, tasks or data etc can be converted to Observables. Whatever the source of the warnings is, if it can implement the IObservable interface it can be used with Rx.
In the simplest case, a Subject can be used to implement a simple observable that only produces events when someone calls its OnNext method. It's generally frowned upon because it's somewhat like using a for loop when a LINQ query is needed, but it's useful to demonstrate how to use Rx:
var eventSource=new Subject<TestEvent>();
//Somewhere where warnings are raise
eventSource.OnNext(new TestEvent { Level = Level.Info });
...
eventSource.OnNext(new TestEvent { Level = Level.Warning });
The Rx library provides methods that transform data, events, tasks etc into observables. For example, FromEventPattern will convert a .NET Pattern into an IObservable:
var eventSource= Observable.FromEventPattern(h => someClass.SomeEvent += h,
h => someClass.someEvent -= h);

Improve the Latency of my cycle in C#(.Net) application

I have a generic question regarding obtaining a very high latency. I am coding for a target device which has Windows Embedded Pro 7. So i would assume that I can get real time performance (from what I have read). I am using "System.Timers" for setting a time cycle.Below is an example in
public void updateCycle50ms( )
{
Stopwatch t = Stopwatch.StartNew();
System.TimeSpan timer50ms = System.TimeSpan.FromMilliseconds(50);
while (1 == 1)
{
// Sending Message
CANSEND(ref msg); // This function sends Message over CAN network.
while (t.Elapsed < timer50ms)
{
// do nothing
}
}
}
What I try to do is send a message every 50 milliSecond, but at the the cycle takes from 29ms to 90ms (I can see it at receiving end). Can you guys tell me why I am not able to achieve my goal. Do I need to use another .Net class or there are special classes which can be used in Windows Embedded to get Real Time Performance (or closer to it).
Try to use System.Timers.Timer class:
private System.Timers.Timer timer;
public void updateCycle50ms( )
{
// Create a timer with a 50ms interval.
timer= new System.Timers.Timer(50);
// Hook up the Elapsed event for the timer.
timer.Elapsed += (s, e) =>
{
// Sending Message
CANSEND(ref msg);
};
// Have the timer fire repeated events (true is the default)
timer.AutoReset = true;
// Start the timer
timer.Enabled = true;
// If the timer is declared in a long-running method, use KeepAlive to prevent garbage collection
// from occurring before the method ends.
// GC.KeepAlive(timer)
}

Timer with two intervals for execution of tasks

I have a c# windows service with a timer that executes a process every 5 minutes.
I don't want to create other process to execute a task every 30 minutes, so is it possible within the same timer timer_Elapsed event to do that logic? any clue?
Thanks a lot,
How about using 2 timers?
You could increment a variable every time the timer elapses, and when that variable reaches 6, you reset it to 0 and execute your 'once every 30 minute' code. Also, creating a new (winform) timer does not create a new thread as far as I know.
int TimerVariable=0;
TimerEvent(object sender,eventargs e)
{
TimerVariable++;
if(TimverVariable>=6)
{
//Execute the once every 30 min code
}
//Execute the once every 5 min code.
}
Well, you could just use a counter and check it against 6(30000/5000) and reset it back to zero when done.
private int counter = 0;
private void TimerCallback()
{
counter++;
if(counter >=6)
{
//Your 30 seconds code here
counter = 0;
}
}

Determining for how long a thread has been running

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.

How to let Timer skip tick if the previous thread is still busy

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

Categories