How to reset an incrementing counter every N minutes - c#

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

Related

In what time interval is the conditions in a while clause checked?

How do I wait for a specified time while showing the remaining time to wait?
I now solved it like this but I feel like this is a really bad way to do it:
//This is running in a BackgroundWorker:
Stopwatch watch = new Stopwatch();
watch.Start();
while(watch.ElapsedMilliseconds != SecondsToWait * 1000)
{
TimeToNextRefresh = ((SecondsToWait * 1000) - watch.ElapsedMilliseconds) / 1000;
Thread.Sleep(1);
}
watch.Stop();
So here I am guessing that the condition (watch.ElapsedMilliseconds != SecondsToWait * 1000) is checked every millisecond.
So the main question is; In what period is the condition of while checked and/or how do I improve the code I've written?
It depends on what's the code inside while loop!
For example, if you write some really long/time-consuming code in a while loop, each iteration of the while loop, or course, will be longer than a while loop that only has short/fast code.
Compare these two while loops:
while (true) {
Console.WriteLine("Hello");
}
and
while (true) {
Console.Beep(5000);
}
Each iteration of the first while loop is faster than that of the second one because Console.Beep(5000) takes 5 seconds and Console.WriteLine only takes a fraction of a second.
So you can't rely on while loops to count time.
This is what you should do:
Create an instance of System.Windows.Forms.Timer, not the System.Timers.Timer nor the System.Threading.Timer. I find the first one the most useful (others are more advanced).
Timer timer = new Timer();
timer.Interval = 1000; // 1000 means 1000ms aka 1 second
timer.Tick += TimerTicked;
timer.Start();
Now the compiler will tell you that TimerTicked is not defined, so let's go define that:
private void TimerTicked(object sender, EventArgs e) {
}
Now you're all set. The code in TimerTicked will be called every one second.
Let's say you want to measure a time of 10 seconds. After 10 seconds, you want to do something. So first create a variable called secondsLeft in the class level:
int secondsLeft = 10;
Now in TimerTicked, you want to check whether secondsLeft is 0. If it is, do that something, else, minus one:
if (secondsLeft == 0) {
DoSomething();
} else {
secondsLeft--;
}
And secondsLeft is the time remaining! You can display it on a label or something.
To pause the timer, simply
timer.Stop();
The exact interval in which your while condition is checked is hard to predict. Thread.Sleep(1); only tells the operating system that you want your thread to sleep for at least 1 millisecond. There is no guarantee that your thread will be active again after exactly 1ms. Actually you can rather be sure that it will be more than that. The thread is scheduled again after 1ms, but there will be a delay until he gets his CPU time slot.
The interval you want for your loop actually depends how you want to display the remaining time. If you want to display only seconds, why would you update that display every millisecond, although the text would change only every 1000ms?
A loop like that is probably not a good way to implement something like that. I would recommend a System.Threading.Timer:
// this Timer will call TimerTick every 1000ms
Timer timer = new Timer(TimerTick, null, 0, 1000);
and implement the handler
public void TimerTick(object sender)
{
// update your display
}
Note that you will have the "update your display" part on the UI thread again, as this method is called by the Timer on a different thread.
This code is can really make an infinite loop if a calculation just take longer than 1 miliseconds.
You can achieve your desired behaviour with a simple System.Winforms.Forms.Timer like this snipped below :
private int tickCount = 0;
private int remaining = 10;
private void timer1_Tick(object sender, EventArgs e)
{
remaining--;
textBox1.Text = remaining.ToString();
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Interval = 1000;
timer1.Enabled = true;
}
With this you can countdown from 10 seconds and every tick you write to a textbox the remaining seconds

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

Executing a Function at a Specific time

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.

How to add a timer to an app!

I have an app that I would like to update on an interval. I am looking for maybe some type of if statement or try - catch statement. I already have a foreach statement in the same class, but i dont think I can put in there? I would also like to set it up so that the user can change the refresh rate. Any help is appreciated. Thanks
Here is the method that I would like to put the timer in...
private void _UpdatePortStatus(string[] files)
{
foreach (string file in files)
{
PortStatus ps = new PortStatus();
ps.ReadXml(new StreamReader(file));
if (!_dicPortStatus.ContainsKey(ps.General[0].Group))
{
_dicPortStatus.Add(ps.General[0].Group, ps);
}
PortStatus psOrig = _dicPortStatus[ps.General[0].Group];
foreach (PortStatus.PortstatusRow psr in ps.Portstatus.Rows)
{
DataRow[] drs = psOrig.Portstatus.Select("PortNumber = '" + psr.PortNumber + "'");
if (drs.Length == 1)
{
DateTime curDt = DateTime.Parse(drs[0]["LastUpdateDateTimeUTC"].ToString());
DateTime newDt = psr.LastUpdateDateTimeUTC;
if (newDt > curDt)
{
drs[0]["LastUpdateDateTimeUTC"] = newDt;
}
}
else if (drs.Length == 0)
{
psOrig.Portstatus.ImportRow(psr);
}
else
{
throw new Exception("More than one of the same portnumber on PortStatus file: " + file);
}
}
}
}
Look at the System.Timer class. You basically set an interval (eg. 10000 milliseconds) and it will raise an event every time that interval time passes.
To allow the use to change the refresh rate, write a method that receives input from the user and use that to update the TimerInterval. Note that the TimerInterval is in miliseconds, so you may need to convert to that from whatever the user input.
So, from the example, the event will be raised every 10 seconds:
System.Timers.Timer aTimer = new System.Timers.Timer(10000); //10 seconds
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Enabled = true; // Starts the Timer
// Specify what you want to happen when the Elapsed event is raised
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
//Perform update
_UpdatePortStatus(files);
}
UPDATE: In response to your posted code, it appears you simply want to call _UpdatePortStatus to update the port status at regular intervals (see the updated example above).
One important point you need to bear in mind though is that the Timer will run on a separate thread, and as such could raise the event again before it has finished running from the last time if it takes more than the interval time to run.
Use System.Timers.Timer, System.Threading.Timer or System.Windows.Forms.Timer ... depending on what exactly it is that you "would like to update on an interval."
See the following articles:
http://www.intellitechture.com/System-Windows-Forms-Timer-vs-System-Threading-Timer-vs-System-Timers-Timer/
http://www.yoda.arachsys.com/csharp/threads/timers.shtml
Your question is somewhat vague as there an many different methods of achieving what you want to do. However in the simplest terms you need to create a System.Threading.Timer that ticks on whatever frequency you define, for example:
private System.Threading.Timer myTimer;
private void StartTimer()
{
myTimer = new System.Threading.Timer(TimerTick, null, 0, 5000);
}
private void TimerTick(object state)
{
Console.WriteLine("Tick");
}
In this example the timer will 'tick' every 5 seconds and perform whatever functionality you code into the TimerTick method. If the user wants to change the frequency then you would destroy the current timer and initialise with the new frequency.
All this said, I must stress that this is the simplest of implementation and may not suit your needs.

.NET, event every minute (on the minute). Is a timer the best option?

I want to do stuff every minute on the minute (by the clock) in a windows forms app using c#. I'm just wondering whats the best way to go about it ?
I could use a timer and set its interval to 60000, but to get it to run on the minute, I would have to enable it on the minute precisely, not really viable.
I could use a timer and set its interval to 1000. Then within its tick event, I could check the clocks current minute against a variable that I set, if the minute has changed then run my code. This worries me because I am making my computer do a check every 1 second in order to carry out work every 1 minutes. Surely this is ugly ?
I'm using windows forms and .Net 2.0 so do not want to use the DispatchTimer that comes with .Net 3.5
This must be a fairly common problem. Have any of you a better way to do this?
Building on the answer from aquinas which can drift and which doesn't tick exactly on the minute just within one second of the minute:
static System.Timers.Timer t;
static void Main(string[] args)
{
t = new System.Timers.Timer();
t.AutoReset = false;
t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
t.Interval = GetInterval();
t.Start();
Console.ReadLine();
}
static double GetInterval()
{
DateTime now = DateTime.Now;
return ((60 - now.Second) * 1000 - now.Millisecond);
}
static void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine(DateTime.Now.ToString("o"));
t.Interval = GetInterval();
t.Start();
}
On my box this code ticks consistently within .02s of each minute:
2010-01-15T16:42:00.0040001-05:00
2010-01-15T16:43:00.0014318-05:00
2010-01-15T16:44:00.0128643-05:00
2010-01-15T16:45:00.0132961-05:00
How about:
int startin = 60 - DateTime.Now.Second;
var t = new System.Threading.Timer(o => Console.WriteLine("Hello"),
null, startin * 1000, 60000);
Creating a Timer control that fires every 1 second (and usually does nothing but a simple check) will add negligible overhead to your application.
Simply compare the value of Environment.TickCount or DateTime.Now to the last stored time (the previous 'minute tick'), and you should have a reasonably precise solution. The resolution of these two time values is about 15ms, which should be sufficient for your purposes.
Do note however that the interval of the Timer control is not guaranteed to be that precise or even anywhere now, since it runs on the Windows message loop, which is tied in with the responsiveness of the UI. Never rely on it for even moderately precise timing - though it is good enough for firing repeating events where you can check the time using a more sensitive method such as one of the two given above.
You can nail this with reactive extensions which will take care of lots of timer related problems for you (clock changes, app hibernation etc). Use Nuget package Rx-Main and code like this:
Action work = () => Console.WriteLine(DateTime.Now.ToLongTimeString());
Scheduler.Default.Schedule(
// start in so many seconds
TimeSpan.FromSeconds(60 - DateTime.Now.Second),
// then run every minute
() => Scheduler.Default.SchedulePeriodic(TimeSpan.FromMinutes(1), work));
Console.WriteLine("Press return.");
Console.ReadLine();
Read here (search for "Introducing ISchedulerPeriodic") to see all the issues this is taking care of: http://blogs.msdn.com/b/rxteam/archive/2012/06/20/reactive-extensions-v2-0-release-candidate-available-now.aspx
I jsut wrote this class using the WPF DispatcherTimer but you can swap the dispatcher for any timer that supports changing when it's woken from sleep state.
The class is constructed with a fixed time step and supprts Start/Stop/Reset, Start/Stop/Start works like a resume operation. The timer is like a stopwatch in that regard.
A clock implementation would simply create the class with a interval of 1 second and listen to the event. Be wary though that this is a real-time clock, if the tick event takes longer than the interval to finish you'll notice that the clock will try and catch up to real-time this will cause a burst of tick events being raised.
public class FixedStepDispatcherTimer
{
/// <summary>
/// Occurs when the timer interval has elapsed.
/// </summary>
public event EventHandler Tick;
DispatcherTimer timer;
public bool IsRunning { get { return timer.IsEnabled; } }
long step, nextTick, n;
public TimeSpan Elapsed { get { return new TimeSpan(n * step); } }
public FixedStepDispatcherTimer(TimeSpan interval)
{
if (interval < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException("interval");
}
this.timer = new DispatcherTimer();
this.timer.Tick += new EventHandler(OnTimerTick);
this.step = interval.Ticks;
}
TimeSpan GetTimerInterval()
{
var interval = nextTick - DateTime.Now.Ticks;
if (interval > 0)
{
return new TimeSpan(interval);
}
return TimeSpan.Zero; // yield
}
void OnTimerTick(object sender, EventArgs e)
{
if (DateTime.Now.Ticks >= nextTick)
{
n++;
if (Tick != null)
{
Tick(this, EventArgs.Empty);
}
nextTick += step;
}
var interval = GetTimerInterval();
Trace.WriteLine(interval);
timer.Interval = interval;
}
public void Reset()
{
n = 0;
nextTick = 0;
}
public void Start()
{
var now = DateTime.Now.Ticks;
nextTick = now + (step - (nextTick % step));
timer.Interval = GetTimerInterval();
timer.Start();
}
public void Stop()
{
timer.Stop();
nextTick = DateTime.Now.Ticks % step;
}
}
Create a method or put this code where you want the timer to start:
int time = 60 - DateTime.Now.Second; // Gets seconds to next minute
refreshTimer.Interval = time * 1000;
refreshTimer.Start();
And then on your tick event set the interval to 60000:
private void refreshTimer_Tick(object sender, EventArgs e)
{
refreshTimer.Interval = 60000; // Sets interval to 60 seconds
// Insert Refresh logic
}
By making use of ReactiveExtensions you could use the following code if you were interested in doing something as simple as printing to the console.
using System;
using System.Reactive.Linq;
namespace ConsoleApplicationExample
{
class Program
{
static void Main()
{
Observable.Interval(TimeSpan.FromMinutes(1))
.Subscribe(_ =>
{
Console.WriteLine(DateTime.Now.ToString());
});
Console.WriteLine(DateTime.Now.ToString());
Console.ReadLine();
}
}
}
Running a bit of code to see if the minute has changed once per second should not require much CPU time, and should be acceptable.
What about Quartz.NET? I think its a good framework to do timed actions.
You could set up two timers. An initial short interval timer (perhaps to fire every second, but dependent on how presice the second timer must fire on the minute).
You would fire the short interval timer only until the desired start time of the main interval timer is reached. Once the initial time is reached, the second main interval timer can be activated, and the short interval timer can be deactivated.
void StartTimer()
{
shortIntervalTimer.Interval = 1000;
mainIntervalTimer.Interval = 60000;
shortIntervalTimer.Tick +=
new System.EventHandler(this.shortIntervalTimer_Tick);
mainIntervalTimer.Tick +=
new System.EventHandler(mainIntervalTimer_Tick);
shortIntervalTimer.Start();
}
private void shortIntervalTimer_Tick(object sender, System.EventArgs e)
{
if (DateTime.Now.Second == 0)
{
mainIntervalTimer.Start();
shortIntervalTimer.Stop();
}
}
private void mainIntervalTimer_Tick(object sender, System.EventArgs e)
{
// do what you need here //
}
Alternatively, you could sleep to pause execution until it times out which should be close to your desired time. This will only wake the computer when the sleep finishes so it'll save you CPU time and let the CPU power down between processing events.
This has the advantage of modifying the timeout so that it will not drift.
int timeout = 0;
while (true) {
timeout = (60 - DateTime.Now.Seconds) * 1000 - DateTime.Now.Millisecond;
Thread.Sleep(timeout);
// do your stuff here
}
Use a timer set to run every second (or millisecond, whatever your accuracy threshold is), and then code the method to run your functionality if and only if the current time is within that threshold past the "on the minute" point.
What I'm using for scheduled tasks is a System.Threading.Timer(System.Threading.TimerCallback, object, int, int) with the callback set to the code I want to execute based on the interval which is supplied in milliseconds for the period value.
What about a combination of aquinas' answer and 'polling': (apologies for the mixture of languages)
def waitForNearlyAMinute:
secsNow = DateTime.Now.Second;
waitFor = 55 - secsNow;
setupTimer(waitFor, pollForMinuteEdge)
def pollForMinuteEdge:
if (DateTime.Now.Second == 0):
print "Hello, World!";
waitForNearlyAMinute();
else:
setupTimer(0.5, pollForMinuteEdge)
I have a solution based on Environment.TickCount
static void Main(string[] args)
{
//constatnt total miliseconds to one minute
const Int32 minuteMilisecond = 60 * 1000;
//get actual datetime
DateTime actualDateTime = DateTime.UtcNow;
//compenzation to one minute
Int32 nexTimer = Environment.TickCount + ((59 - actualDateTime.Second) * 1000) + (999 - actualDateTime.Millisecond);
//random fuction to simulate different delays on thread
Random rnd = new Random();
//main loop
while (true)
{
if (Environment.TickCount > nexTimer)
{
nexTimer += minuteMilisecond;
//execute your code here every minute
Console.WriteLine($"actual DateTime: {DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss:ffff")}");
}
//random sleep between 100 - 200 ms
Thread.Sleep(rnd.Next(100, 200));
}
}

Categories