I am writing a class named Food. I considered a field “int cookingTime” to see how long each instance of this class has been existed. I assumed I should use the Timer class. I wrote the following piece of code but it did not work. I am not sure if my approach is correct . I really appreciate any help.
Class Food
{
private System.Timers.Timer timerClock = new System.Timers.Timer();
static int cookingTime = 0;
public Food()
{
this.timerClock.Elapsed += new System.Timers.ElapsedEventHandler(process);
this.timerClock.Interval = 1000;
this.timerClock.Enabled = true;
}
static void process(Object myObject, EventArgs myEventArgs)
{
cookingTime += 1;
}
}
How about saving the timestamp of the creation of the object? Then just subtrackt that from Now() when you want to know how long the object has existed.
Why not use System.Diagnostics.Stopwatch?
class Food
{
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
public TimeSpan CookingTime
{
get { return _stopwatch.Elapsed; }
}
}
I notice that your cookingTime field is static. If you are somehow totalling the times of multiple foods, then you might keep a list (static or otherwise) of Stopwatches, and whenever you need to know the total time, you could sum them all together.
Related
I'm making a service. Among other things, it must read the value from registry and configure "Primary" timers' interval according to this value. Now it should do it not only in constructor phase, but also be able to change this interval when it has been changed in registry. How do I do that?
In other words, I have a code like this:
using System.Timers;
public static class GVARS
{
public static Config valFromRegistry = new ConfigRegistry().Result;
}
class Program
{
static void Main(string[] args)
{
int timerPeriod = (int)(uint)GVARS.valFromRegistry.Interval * 60000;
Timer primaryTimer = new Timer(timerPeriod);
primaryTimer.Interval = timerPeriod;
primaryTimer.Elapsed += RunPrimaryPayload;
primaryTimer.Start();
Console.ReadLine();
}
private static void RunPrimaryPayload(object sender, ElapsedEventArgs eventArgs)
{
SomeClass.SomeMethod(someArgs);
GVARS.valFromRegistry.Interval = (int)someNewValue;
}
}
Somewhere down the code I might change valFromRegistry.Interval and I want primaryTimer to respond to those changes. How do I get there?
PS. It's not really important to me how I'm gonna check for changes in registry, be it another timer or event. Whatever works.
PS2. I have a possible idea to use System.Threading.Timer for primaryTimer instead of System.Timers.Timer since the former has method Change() which I might call from another little configrationUpdateTimer every minute or so and make primaryTimer respond to configuration changes this way. Am I right?
Ok, I've managed to solve my problem by creating class with 2 Timers: one checking for config changes (master) and another (slave) is doing actual payload:
public class UniversalTimer
{
public System.Threading.Timer MasterTimer;
public System.Threading.Timer SlaveTimer;
private int lastMainTimerInterval = 0;
public UniversalTimer()
{
MasterTimer = new System.Threading.Timer(new System.Threading.TimerCallback(MasterTimerCallback), null, 0, 60000);
SlaveTimer = new System.Threading.Timer(new System.Threading.TimerCallback(SlaveTimerCallback), null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
}
private void MasterTimerCallback(object obj)
{
Log.Debug("[{0}:{1}:{2}] Re-reading configuration from registry", "Program", "UniversalTimer", "MasterTimerCallback");
var currentSettings = new ConfigRegistry().Result;
if ((int)currentSettings.Interval != lastMainTimerInterval)
{
Log.Debug("[{0}:{1}:{2}] Setting interval for Main Timer", "Program", "UniversalTimer", "SlaveTimerCallback");
lastMainTimerInterval = (int)currentSettings.Interval;
this.MainTimer.Change(0, (int)currentSettings.Interval * 60000);
}
}
private void SlaveTimerCallback(object obj)
{
Log.Debug("[{0}:{1}:{2}] Executing main cycle", "Program", "UniversalTimer", "SlaveTimerCallback");
}
public void Dispose()
{
MasterTimer.Dispose();
SlaveTimer.Dispose();
}
}
Iv'e created a timer using dispatcher time :
time = new DispatcherTimer();
time.Interval = new TimeSpan(0, 0, 0, 0, 80);
and I use it for the speed of an object.Each tick the objects moves 10 pixels.
I would like to know how to increase the speed of the object without changing the pixels it moves each tick, meaning I want to make the timer itself faster during run time every 10 seconds or so.
Is there a way I can do it?Ive tried making a variable speed=0 and increasing it each time I count 10 and then
time.Interval = new TimeSpan(0, 0, 0, 0, 80-speed);
but The object stayed in the same speed.So do I have to make my own timer class instead of using the built in dispatcher time, if so how do I do that?or is there another solution for this?
I think that DispatcherTimer is not your best ally for this task. The class is by no means designed to execute actions at precise intervals.
I'll try to better explain myself: even if the DispatcherTimer, as its name suggests, dispatches actions timely and with a great precision, the dispatched actions will be queued and then executed when the underlying GUI thread decides to process them.
Normally, a GUI thread has a resolution of around 8ms (it's an approximation, but I don't think we need to measure this right now)... and you are using a starting Interval of 80ms that is going to decrease over time until it probably goes beyond that tolerance limit of 8ms or so. In the meanwhile, you are also repainting your interface (or part of it) over and over and this impacts the performance and the responsiveness of the GUI even more: if the GUI thread is busy repainting and that requires more than the Interval value to be accomplished, the next dispatched action will be processed only once the GUI thread completes the undergoing task.
If you need a more precise scheduling, avoiding hangings / losses of responsiveness / delayed actions, you need to use a timer class that runs in background like System.Threading.Timer (google for SyncronizationContext, that would be helpful) or System.Timers.Timer.
On the top of that, never play with intervals when showing a change in speed. Work with a fixed interval and increase/decrease the movement "size" in pixels. You should be able to calculate the delta without problems. Just to make things clearer: if I want to slow that the speed of an object doubled, I don't half the timer interval that draws the object, but I double the amount of pixels my object traverses at each step.
using System;
using System.Collections.Generic;
using System.Linq;
namespace CQRS_and_EventSourcing
{
internal class Program
{
//CQRS = command query responsibility segregation
//CQS= command query separation
//COMMAND
public class PersonStroge
{
Dictionary<int, Person> people;
}
public class Person
{
public int UniqueId;
public int age;
EventBroker broker;
public Person(EventBroker broker)
{
this.broker = broker;
broker.Commands += BrokerOnCommands;
broker.Queries += BrokeronQueries;
}
private void BrokeronQueries(object sender, Query query)
{
var ac = query as AgeQuery;
if (ac != null && ac.Target == this)
{
ac.Result = age;
}
}
private void BrokerOnCommands(object sender, Command command)
{
var cac = command as ChangeAgeCommand;
if (cac != null && cac.Target == this)
{
if (cac.Register)
broker.AllEvents.Add(new AgeChangedEvent(this, age, cac.Age));
age = cac.Age;
}
}
public bool CanVote => age >= 16;
}
public class EventBroker
{
//1. All events that happened.
public IList<Event> AllEvents = new List<Event>();
//2. Commands
public event EventHandler<Command> Commands;
//3. Query
public event EventHandler<Query> Queries;
public void Command(Command c)
{
Commands?.Invoke(this, c);
}
public T Query<T>(Query q)
{
Queries?.Invoke(this, q);
return (T)q.Result;
}
public void UndoLast()
{
var e = AllEvents.LastOrDefault();
var ac = e as AgeChangedEvent;
if (ac != null)
{
Command(new ChangeAgeCommand(ac.Target, ac.OldValue) { Register = false });
AllEvents.Remove(e);
}
}
}
public class Query
{
public object Result;
}
public class AgeQuery : Query
{
public Person Target;
}
public class Command : EventArgs
{
public bool Register = true;
}
public class ChangeAgeCommand : Command
{
public Person Target;
//public int TargetId;
public int Age;
public ChangeAgeCommand(Person target, int age)
{
Target = target;
Age = age;
}
}
public class Event
{
//backtrack
}
public class AgeChangedEvent : Event
{
public Person Target;
public int OldValue, NewValue;
public AgeChangedEvent(Person target, int oldValue, int newValue)
{
Target = target;
OldValue = oldValue;
NewValue = newValue;
}
public override string ToString()
{
return $"Age changed from {OldValue} to {NewValue}";
}
}
static void Main(string[] args)
{
var eb = new EventBroker();
var p = new Person(eb);
eb.Command(new ChangeAgeCommand(p, 123));
foreach (var e in eb.AllEvents)
{
Console.WriteLine(e);
}
//int age;
//age = eb.Query<int>(new AgeQuery { Target = p });
//Console.WriteLine(age);
//eb.UndoLast();
//foreach (var e in eb.AllEvents)
//{
// Console.WriteLine(e);
//}
//age = eb.Query<int>(new AgeQuery { Target = p });
//Console.WriteLine(age);
Console.ReadKey();
}
}
}
İf you couldnt make look at this repository;
[1]:https://github.com/kYasinAblay/DNesteruk.Additional.Lectures/blob/master/CQRS_and_EventSourcing/Program.cs
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.
I'm currently abstracting the concept of timers so that my classes that need one can use mock timers in tests or different implementations in operative mode (e.g. threadpool timers, thread-affine timers, etc.). Therefore, I created this interface:
public interface ITimer : IDisposable
{
bool IsEnabled { get; }
bool IsAutoResetting { get; set; }
TimeSpan Interval { get; set; }
void Start();
void Stop();
event EventHandler IntervalElapsed;
}
Now I want to create a wrapper that adapts the System.Threading.Timer class and implements that interface. I want to do it using test-driven development. My class currently looks somewhat like this:
public sealed class ThreadPoolTimer : ITimer
{
private readonly Timer _timer;
public bool IsEnabled { get; private set; }
public bool IsAutoResetting { get; set; }
public TimeSpan Interval { get; set; }
public ThreadPoolTimer()
{
Interval = this.GetDefaultInterval();
_timer = new Timer(OnTimerCallback);
}
public void Dispose()
{
_timer.Dispose();
}
public void Start()
{
}
public void Stop()
{
}
private void OnTimerCallback(object state)
{
OnIntervalElapsed();
}
public event EventHandler IntervalElapsed;
private void OnIntervalElapsed()
{
var handler = IntervalElapsed;
if (handler != null)
handler(this, EventArgs.Empty);
}
}
My actual question is: how would you write unit tests that describe the (soft real-time) requirements for the behavior of Start, Stop and IntervalElapsed?
In my opinion, i should use e.g. an AutoResetEvent and check if the event is raised within a certain timespan (maybe +/- 3ms). But writing that code somewhat violates the DAMP (descriptive and meaningful phrases) principle, I think. Is there an easier way to do this?
Should I make the dependency to System.Threading.Timer external and then maybe use a shim for testing purposes? Unfortunately, the .NET timers do not have a common interface (which would make my work obsolete...)
What are your thoughts on that topic? Is there any documentation that I have not found yet and that I should read?
Sorry for having actually more than one question in this post, but this testing of soft real-time requirements is quite interesting, I think.
As no one answered this question yet, I'll tell you how I approached the problem: I used the spy pattern to actually implement the code that observes the behavior of the timer. The class looks like this:
public class ThreadPoolTimerSpy : IDisposable
{
private readonly ThreadPoolTimer _threadPoolTimer;
private int _intervalElapsedCallCount;
private readonly ManualResetEvent _resetEvent = new ManualResetEvent(false);
public int NumberOfIntervals { get; set; }
public DateTime StartTime { get; private set; }
public DateTime EndTime { get; private set; }
public ThreadPoolTimerSpy(ThreadPoolTimer threadPoolTimer)
{
if (threadPoolTimer == null) throw new ArgumentNullException("threadPoolTimer");
_threadPoolTimer = threadPoolTimer;
_threadPoolTimer.IntervalElapsed += OnIntervalElapsed;
NumberOfIntervals = 1;
}
public void Measure()
{
_intervalElapsedCallCount = 0;
_resetEvent.Reset();
StartTime = DateTime.Now;
_threadPoolTimer.Start();
_resetEvent.WaitOne();
}
private void OnIntervalElapsed(object sender, EventArgs arguments)
{
_intervalElapsedCallCount++;
if (_intervalElapsedCallCount < NumberOfIntervals)
return;
_threadPoolTimer.Stop();
EndTime = DateTime.Now;
_resetEvent.Set();
}
public void Dispose()
{
_threadPoolTimer.Dispose();
_resetEvent.Dispose();
}
}
This class takes a ThreadPoolTimer and registers to its IntervalElapsed event. One can specify how much intervals the spy should wait until it stops measuring. As I'm using a ManualResetEvent to block the thread that starts the timer in the Measure method, all calls to that method are synchronous, which results in DAMP code in the actual test class, in my opinion.
A test method that uses the spy would look like this:
[TestInitialize]
public void InitializeTestEnvironment()
{
_testTarget = new ThreadPoolTimerBuilder().WithAutoResetOption(true)
.WithInterval(100)
.Build() as ThreadPoolTimer;
Assert.IsNotNull(_testTarget);
_spy = new ThreadPoolTimerSpy(_testTarget);
}
[TestMethod]
public void IntervalElapsedMustBeRaisedExactlyTenTimesAfter1000Milliseconds()
{
CheckIntervalElapsed(10, TimeSpan.FromMilliseconds(1000), TimeSpan.FromMilliseconds(100));
}
private void CheckIntervalElapsed(int numberOfIntervals, TimeSpan expectedTime, TimeSpan toleranceInterval)
{
_spy.NumberOfIntervals = numberOfIntervals;
_spy.Measure();
var passedTime = _spy.EndTime - _spy.StartTime;
var timingDifference = Math.Abs(expectedTime.Milliseconds - passedTime.Milliseconds);
Assert.IsTrue(timingDifference <= toleranceInterval.Milliseconds, string.Format("Timing difference: {0}", timingDifference));
}
If you have any questions or recommendations, please feel free to leave a comment.
Besides: the tolerance interval I have to choose to make the tests pass are relatively high. I thought that maybe 3 to 5 milliseconds might suffice, but in the end for ten intervals I figured out that the actual measured time span is up to 72ms different than the expected time of 1000ms in this case. Well, never use a managed runtime for real time applications, I guess...
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.