I am making a console application that will later be a Windows service application through Topshelf.
I am struggling with timers, I setup a timer with autoreset of 20 seconds. When I start the timer it works. And when I stop it it stops.
Now to the problem, I want to keep the value when stopping it.
I need an event handler as Timer offers. But I also need to have a way that remembers the time as Stopwatch does. Which should I choose? I have access to SQL server and save it.
Lets say I let it run for 10 seconds since autoreset is true, when I stop it. And then wait, and then start the timer again.
In my opinion, the next time I start the timer it should only run for 10 seconds. So the total time that fires up the event is 20 second and not 30.
Is there any way to "save" elapsed time on it?
public class MySampleClient
{
System.Timers.Timer BatchTimer;
public MySampleClient()
{
BatchTimer = new System.Timers.Timer(BatchSampleTimer) { AutoReset = true };
}
public async Task startSession()
{
BatchTimer.Elapsed += BatchTimerVoid;
}
public void BatchIDTrigger(BatchTagDataModel btdm)
{
string btdmValue = btdm.Value.ToLower();
if (batchNumberTimerControllerList.Contains(btdm.DisplayName))
{
if (btdmValue == "true")
{
BatchTimer.Start();
}
else
{
BatchTimer.Stop();
}
}
}
public void BatchTimerVoid(Object source, System.Timers.ElapsedEventArgs e)
{
// Something happens here every 20 seconds.
}
}
I have written a simple extension to a System.Timers.Timer to provide you with a Pause() method. It uses a backing System.Diagnostics.Stopwatch to modify the Timer.Interval according to the elapsed period before the pause.
public class ExtendedTimer: System.Timers.Timer
{
public long MillisecondsElapsed { get { return backingStopwatch.ElapsedMilliseconds; } }
public new double Interval { get; private set; }
private Stopwatch backingStopwatch;
public ExtendedTimer(double interval) : base(interval)
{
Interval = interval;
backingStopwatch = new Stopwatch();
base.Elapsed += ExtendedTimer_Elapsed;
}
private void ExtendedTimer_Elapsed(object sender, ElapsedEventArgs e)
{
base.Interval = this.Interval;
backingStopwatch.Restart();
}
public new void Start()
{
base.Interval = this.Interval - backingStopwatch.ElapsedMilliseconds;
base.Start();
backingStopwatch.Start();
}
public new void Stop()
{
base.Stop();
backingStopwatch.Reset();
}
public void Pause()
{
base.Stop();
backingStopwatch.Stop();
}
}
Since there is now some overhead introduced, I cannot speak to how accurately it will maintain precision timings compared to the original implementation.
Related
public class AuctionTimer : IDisposable
{
public static readonly ConcurrentDictionary<string, AuctionTimer> Timers;
private readonly Timer timer;
static AuctionTimer()
{
Timers = new ConcurrentDictionary<string, AuctionTimer>();
}
private AuctionTimer(string AuctionID, int ExecutionTime)
{
this._AuctionID = AuctionID;
timer = new Timer();
TimeCount = ExecutionTime;
timer.Interval = new TimerUtil().getAuctionInterval();
timer.Elapsed += (s, e) => MonitorElapsedTime();
timer.Start();
}
private int TimeCount { get; set; }
private string _AuctionID { get; set; }
public static void StartTimer(string AuctionID, int ExecutionTime)
{
var newTimer = new AuctionTimer(AuctionID, ExecutionTime);
if (!Timers.TryAdd(AuctionID, newTimer))
{
newTimer.Dispose();
}
}
public static void StopTimer(string AuctionID)
{
AuctionTimer oldTimer;
if (Timers.TryRemove(AuctionID, out oldTimer))
{
oldTimer.Dispose();
}
}
public void Dispose()
{
// Stop might not be necessary since we call Dispose
timer.Stop();
timer.Dispose();
}
private void MonitorElapsedTime()
{
if (TimeCount == new TimerUtil().getAuctionInterval())
{
StopTimer(_AuctionID);
//do the other process in db
}
else
{
TimeCount++;
}
}
}
Following is the code for my Auction Timer what i am trying to do here is making an auction storing starting and ending date so lets say an auction is going to last for 5 hours so the end date will be 5 hours from current time i am starting the Auction timer right after storing the end date for the auction it is working as expected but the problem i am facing now is the timer is bit delay from the end time around 2,3 minutes roughly that's means the process which is suppose to run immediately after the auction expires is running 2,3 minutes late i am not really sure what i am missing here.
I was able to solve this problem using this framework.
I want to have a timer in my windows phone 8 app, that´s counting/running independent of current shown page.
It should connect to server - when possible in a UI independet task/thread - and store data in a global object/list.
The Independence from current shown page is my point.
I tried following in App.xaml.cs:
public partial class App : Application
{
// creating timer instance
DispatcherTimer gAppTimer = new DispatcherTimer();
// timer interval specified as 1 minute
gAppTimer.Interval = TimeSpan.FromSeconds(60);
// Sub-routine OnTimerTick that will be called at specified intervall
gAppTimer.Tick += OnTimerTick;
// starting the timer
gAppTimer.Start();
public void OnTimerTick(Object sender, EventArgs args)
{
// text box property is set to current system date.
// ToString() converts the datetime value into text
MessageBox.Show("TIMER fired");
}
:
:
But this doesn´t work. Than I tried just declaring the object in App.xaml.cs:
public partial class App : Application
{
// creating timer instance
DispatcherTimer gAppTimer = new DispatcherTimer();
public void OnTimerTick(Object sender, EventArgs args)
{
// text box property is set to current system date.
// ToString() converts the datetime value into text
MessageBox.Show("TIMER fired");
}
:
:
And on my startpage.xaml.cs:
// timer interval specified as 1 minute
App.gAppTimer.Interval = TimeSpan.FromSeconds(60);
// Sub-routine OnTimerTick that will be called at specified intervall
App.gAppTimer.Tick += OnTimerTick;
// starting the timer
App.gAppTimer.Start();
But this doesn´t work, too.
Any ideas how to handle my Problem? What I don´t want to use is a Background Task, because it runs only every 30 minutes. My solution should only run, if the app is "active" (in foreground).
That's normally done using a static or singleton class. Both will be global and you'll have access to them from every page.
Also, the DispatcherTimer invokes it's TimerTick method on the UI thread. If you don't need to be in the UI thread, you should use a System.Threading.Timer, which invokes a method in a background thread.
Here's an example:
public static class SomeManager {
private static Timer gAppTimer;
private static object lockObject = new object();
public static void StartTimer() {
if (gAppTimer == null) {
lock (lockObject) {
if (gAppTimer == null) {
gAppTimer = new Timer(OnTimerTick, null, 60 * 1000, 60 * 1000);
}
}
}
}
public static void StopTimer() {
if (gAppTimer != null) {
lock (lockObject) {
if (gAppTimer != null) {
gAppTimer.Change(Timeout.Infinite, Timeout.Infinite);
gAppTimer = null;
}
}
}
}
private static void OnTimerTick(object state) {
Action();
}
public static void Action() {
// Do what you need to do
}
}
Just call SomeManager.StartTimer() from your first page or from App.xaml.cs and the timer will start.
Update
I updated the code a little:
Renamed the Initialize method to StartTimer.
Added StopTimer method which stops the timer. You can then start it again by calling SomeManager.StartTimer.
Added Action method which is the one actually donig the work. You can invoke it from anywhere, anytime.
Note: the the timer will call this method in a background thread and you should do the same using something like Task.Run(() => SomeManager.Action());
Added a lock to ensure that the Start/Stop methods will not throw exceptions if invoked from multiple threads at the same time.
I'm not sure how you have arranged your code, but as I've tried:
public partial class App : Application
{
public static PhoneApplicationFrame RootFrame { get; private set; }
public DispatcherTimer gAppTimer = new DispatcherTimer();
public void OnTimerTick(Object sender, EventArgs args)
{
MessageBox.Show("TIMER fired");
}
public App()
{
gAppTimer.Interval = TimeSpan.FromSeconds(2);
// Sub-routine OnTimerTick that will be called at specified intervall
gAppTimer.Tick += OnTimerTick;
// starting the timer
gAppTimer.Start();
// rest of the code
the above code works. MessageBox shows every 2 seconds, if you had declared your DispatcherTimer as public, then you will be able to access it like this:
(App.Current as App).gAppTimer.Stop();
Note also that depending on what you want to achieve you may also use System.Threading.Timer.
On the other hand you may also think of using public static DispatcherTimer somewhere.
Hi I have a similar problem to an old thread that I still can't work around
(Pass a return value back through an EventHandler) . I am eventually trying to implement a timer that will calculate velocity at even intervals so I require the Elapsed Time Event to return some kind of value. I've tried using global variables but the event doesn't seem to change the variable. Any advice? Thanks in advance!
namespace Timer_Label
{
public static class GlobalVariables
{
public static int _stringHolder;
public static int StringHolder
{
get { return _stringHolder; }
set { _stringHolder = value; }
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
System.Timers.Timer myTimer = new System.Timers.Timer();
myTimer.Elapsed += new ElapsedEventHandler(DisplayTimeEvent);
myTimer.Interval = 500;
myTimer.Start();
MessageBox.Show(Convert.ToString(GlobalVariables.StringHolder));
}
public static void DisplayTimeEvent(object sender, ElapsedEventArgs e)
{
GlobalVariables.StringHolder = "1";
}
It's highly improbable that the timer will have expired by the time the code reaches your MessageBox.Show statement.
Try placing a Thread.Sleep(1000) call between myTimer.Start() and MessageBox.Show(). This should give the timer time to elapse and execute your DisplayTimeEvent handler.
Eventually, you will need to take into account the fact that the System.Timer.Timer class executes its callback in a background thread, so changes that you make in DisplayTimeEvent will need to be synchronized.
There's plenty of examples of people saying to use a Timer instead of Thread.Sleep(...) in an Azure Worker Role. No probs with that.
What I'm struggling to understand is how to code this.
Currently, I have the following (pseduo code)
_timer.Elapsed += (sender, args) => DoWork();
public override void Run()
{
while(true)
{
DoWork();
}
}
public void DoWork()
{
try
{
_timer.Stop();
// Now - do stuff ....
}
catch(....) { ... }
_timer.Start()
}
And what happens, is that the code enters the DoWork() method once and DoesStuff(tm).. fine .. starts the timer (say .. with a 30 second interval) and then exits that method.
Then, it returns back to the main Run() method .. which is in that loop. So it immediately comes back around and enters the DoWork() method again .. instead of waiting for the timer to fire it off.
So I'm not sure how to replace any Thread.Sleep(...) with Timers.
Any clues?
Clarification
I do not want to exit the Run() method :) I'm very happy to keep looping forever. What I'm stuck with, is replacing the standard Thread.Sleep(...) call (which blocks the thread) and replace that with a Timer, which most people suggest.
Update
Please do not link or suggest that I should use cancelSource.Token.WaitHandle.WaitOne(); as a solution. That is not what I'm trying to achieve here. Please note the post title!
I figure that if you want to solve this situation the way you outline here you will need a WaitHandle AND a Timer.
The short answer is here below. The long answer became a blog post: HowTo wait in a WorkerRole using Timer and EventWaitHandle over Thread.Sleep
I used an EventWaitHandle along with the Timer and came up with this solution:
public class WorkerRole : RoleEntryPoint
{
Waiter waiter;
public override bool OnStart()
{
waiter = new Waiter(WorkerConfiguration.WaitInterval);
return base.OnStart();
}
public override void Run()
{
while (true)
{
DoWork();
waiter.Wait();
}
}
public void DoWork()
{
// [...]
}
}
And here is the waiter class:
public class Waiter
{
private readonly Timer timer;
private readonly EventWaitHandle waitHandle;
public Waiter(TimeSpan? interval = null)
{
waitHandle = new AutoResetEvent(false);
timer = new Timer();
timer.Elapsed += (sender, args) => waitHandle.Set();
SetInterval(interval);
}
public TimeSpan Interval
{
set { timer.Interval = value.TotalMilliseconds; }
}
public void Wait(TimeSpan? newInterval = null)
{
SetInterval(newInterval);
timer.Start();
waitHandle.WaitOne();
timer.Close();
waitHandle.Reset();
}
private void SetInterval(TimeSpan? newInterval)
{
if (newInterval.HasValue)
{
Interval = newInterval.Value;
}
}
}
I'm not really writing an alarm clock application, but it will help to illustrate my question.
Let's say that I have a method in my application, and I want this method to be called every hour on the hour (e.g. at 7:00 PM, 8:00 PM, 9:00 PM etc.). I could create a Timer and set its Interval to 3600000, but eventually this would drift out of sync with the system clock. Or I could use a while() loop with Thread.Sleep(n) to periodically check the system time and call the method when the desired time is reached, but I don't like this either (Thread.Sleep(n) is a big code smell for me).
What I'm looking for is some method in .Net that lets me pass in a future DateTime object and a method delegate or event handler, but I haven't been able to find any such thing. I suspect there's a method in the Win32 API that does this, but I haven't been able to find that, either.
Or, you could create a timer with an interval of 1 second and check the current time every second until the event time is reached, if so, you raise your event.
You can make a simple wrapper for that :
public class AlarmClock
{
public AlarmClock(DateTime alarmTime)
{
this.alarmTime = alarmTime;
timer = new Timer();
timer.Elapsed += timer_Elapsed;
timer.Interval = 1000;
timer.Start();
enabled = true;
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(enabled && DateTime.Now > alarmTime)
{
enabled = false;
OnAlarm();
timer.Stop();
}
}
protected virtual void OnAlarm()
{
if(alarmEvent != null)
alarmEvent(this, EventArgs.Empty);
}
public event EventHandler Alarm
{
add { alarmEvent += value; }
remove { alarmEvent -= value; }
}
private EventHandler alarmEvent;
private Timer timer;
private DateTime alarmTime;
private bool enabled;
}
Usage:
AlarmClock clock = new AlarmClock(someFutureTime);
clock.Alarm += (sender, e) => MessageBox.Show("Wake up!");
Please note the code above is very sketchy and not thread safe.
Interesting, I've actually come across a very similar issue and went looking for a method in the .Net framework that would handle this scenario. In the end, we ended up implementing our own solution that was a variation on a while loop w/ Thread.Sleep(n) where n gets smaller the closer you get to the desired target time (logarithmically actually, but with some reasonable thresholds so you're not maxing the cpu when you get close to the target time.) Here's a really simple implementation that just sleeps half the time between now and the target time.
class Program
{
static void Main(string[] args)
{
SleepToTarget Temp = new SleepToTarget(DateTime.Now.AddSeconds(30),Done);
Temp.Start();
Console.ReadLine();
}
static void Done()
{
Console.WriteLine("Done");
}
}
class SleepToTarget
{
private DateTime TargetTime;
private Action MyAction;
private const int MinSleepMilliseconds = 250;
public SleepToTarget(DateTime TargetTime,Action MyAction)
{
this.TargetTime = TargetTime;
this.MyAction = MyAction;
}
public void Start()
{
new Thread(new ThreadStart(ProcessTimer)).Start();
}
private void ProcessTimer()
{
DateTime Now = DateTime.Now;
while (Now < TargetTime)
{
int SleepMilliseconds = (int) Math.Round((TargetTime - Now).TotalMilliseconds / 2);
Console.WriteLine(SleepMilliseconds);
Thread.Sleep(SleepMilliseconds > MinSleepMilliseconds ? SleepMilliseconds : MinSleepMilliseconds);
Now = DateTime.Now;
}
MyAction();
}
}
You could simply reset the timer duration each time it fires, like this:
// using System.Timers;
private void myMethod()
{
var timer = new Timer {
AutoReset = false, Interval = getMillisecondsToNextAlarm() };
timer.Elapsed += (src, args) =>
{
// Do timer handling here.
timer.Interval = getMillisecondsToNextAlarm();
timer.Start();
};
timer.Start();
}
private double getMillisecondsToNextAlarm()
{
// This is an example of making the alarm go off at every "o'clock"
var now = DateTime.Now;
var inOneHour = now.AddHours(1.0);
var roundedNextHour = new DateTime(
inOneHour.Year, inOneHour.Month, inOneHour.Day, inOneHour.Hour, 0, 0);
return (roundedNextHour - now).TotalMilliseconds;
}
You could create an Alarm class which has a dedicated thread which goes to sleep until the specified time, but this will use the Thread.Sleep method. Something like:
/// <summary>
/// Alarm Class
/// </summary>
public class Alarm
{
private TimeSpan wakeupTime;
public Alarm(TimeSpan WakeUpTime)
{
this.wakeupTime = WakeUpTime;
System.Threading.Thread t = new System.Threading.Thread(TimerThread) { IsBackground = true, Name = "Alarm" };
t.Start();
}
/// <summary>
/// Alarm Event
/// </summary>
public event EventHandler AlarmEvent = delegate { };
private void TimerThread()
{
DateTime nextWakeUp = DateTime.Today + wakeupTime;
if (nextWakeUp < DateTime.Now) nextWakeUp = nextWakeUp.AddDays(1.0);
while (true)
{
TimeSpan ts = nextWakeUp.Subtract(DateTime.Now);
System.Threading.Thread.Sleep((int)ts.TotalMilliseconds);
try { AlarmEvent(this, EventArgs.Empty); }
catch { }
nextWakeUp = nextWakeUp.AddDays(1.0);
}
}
}
I know it's a bit of an old question, but I came across this when I was looking for an answer to something else. I thought I'd throw my two cents in here, since I recently had this particular issue.
Another thing you can do is schedule the method like so:
/// Schedule the given action for the given time.
public async void ScheduleAction ( Action action , DateTime ExecutionTime )
{
try
{
await Task.Delay ( ( int ) ExecutionTime.Subtract ( DateTime.Now ).TotalMilliseconds );
action ( );
}
catch ( Exception )
{
// Something went wrong
}
}
Bearing in mind it can only wait up to the maximum value of int 32 (somewhere around a month), it should work for your purposes. Usage:
void MethodToRun ( )
{
Console.WriteLine ("Hello, World!");
}
void CallingMethod ( )
{
var NextRunTime = DateTime.Now.AddHours(1);
ScheduleAction ( MethodToRun, NextRunTime );
}
And you should have a console message in an hour.
What about System.Timers.Timer class ? See http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
I have used this before with great success:
Vb.net:
Imports System.Threading
Public Class AlarmClock
Public startTime As Integer = TimeOfDay.Hour
Public interval As Integer = 1
Public Event SoundAlarm()
Public Sub CheckTime()
While TimeOfDay.Hour < startTime + interval
Application.DoEvents()
End While
RaiseEvent SoundAlarm()
End Sub
Public Sub StartClock()
Dim clockthread As Thread = New Thread(AddressOf CheckTime)
clockthread.Start()
End Sub
End Class
C#:
using System.Threading;
public class AlarmClock
{
public int startTime = TimeOfDay.Hour;
public int interval = 1;
public event SoundAlarmEventHandler SoundAlarm;
public delegate void SoundAlarmEventHandler();
public void CheckTime()
{
while (TimeOfDay.Hour < startTime + interval) {
Application.DoEvents();
}
if (SoundAlarm != null) {
SoundAlarm();
}
}
public void StartClock()
{
Thread clockthread = new Thread(CheckTime);
clockthread.Start();
}
}
I don't know if the c# works, but the vb works just fine.
Usage in VB:
Dim clock As New AlarmClock
clock.interval = 1 'Interval is in hours, could easily convert to anything else
clock.StartClock()
Then, just add an event handler for the SoundAlarm event.