How would I go about implementing a stopwatch with different speeds? - c#

Ideally I would like to have something similar to the Stopwatch class but with an extra property called Speed which would determine how quickly the timer changes minutes. I am not quite sure how I would go about implementing this.
Edit
Since people don't quite seem to understand why I want to do this. Consider playing a soccer game, or any sport game. The halfs are measured in minutes, but the time-frame in which the game is played is significantly lower i.e. a 45 minute half is played in about 2.5 minutes.

Subclass it, call through to the superclass methods to do their usual work, but multiply all the return values by Speed as appropriate.

I would use the Stopwatch as it is, then just multiply the result, for example:
var Speed = 1.2; //Time progresses 20% faster in this example
var s = new Stopwatch();
s.Start();
//do things
s.Stop();
var parallelUniverseMilliseconds = s.ElapsedMilliseconds * Speed;

The reason your simple "multiplication" doesn't work is that it doesn't speeding up the passing of time - the factor applies to all time that has passed, as well as time that is passing.
So, if you set your speed factor to 3 and then wait 10 minutes, your clock will correctly read 30 minutes. But if you then change the factor to 2, your clock will immediately read 20 minutes because the multiplication is applied to time already passed. That's obviously not correct.
I don't think the stopwatch is the class you want to measure "system time" with. I think you want to measure it yoruself, and store elapsed time in your own variable.
Assuming that your target project really is a game, you will likely have your "game loop" somewhere in code. Each time through the loop, you can use a regular stopwatch object to measure how much real-time has elapsed. Multiply that value by your speed-up factor and add it to a separate game-time counter. That way, if you reduce your speed factor, you only reduce the factor applied to passing time, not to the time you've already recorded.
You can wrap all this behaviour into your own stopwatch class if needs be. If you do that, then I'd suggest that you calculate/accumulate the elapsed time both "every time it's requested" and also "every time the factor is changed." So you have a class something like this (note that I've skipped field declarations and some simple private methods for brevity - this is just a rough idea):
public class SpeedyStopwatch
{
// This is the time that your game/system will run from
public TimeSpan ElapsedTime
{
get
{
CalculateElapsedTime();
return this._elapsedTime;
}
}
// This can be set to any value to control the passage of time
public double ElapsedTime
{
get { return this._timeFactor; }
set
{
CalculateElapsedTime();
this._timeFactor = value;
}
}
private void CalculateElapsedTime()
{
// Find out how long (real-time) since we last called the method
TimeSpan lastTimeInterval = GetElapsedTimeSinceLastCalculation();
// Multiply this time by our factor
lastTimeInterval *= this._timeFactor;
// Add the multiplied time to our elapsed time
this._elapsedTime += lastTimeInterval;
}
}

According to modern physics, what you need to do to make your timer go "faster" is to speed up the computer that your software is running one. I don't mean the speed at wich it performs calculations, but the physical speed. The close you get to the speed of light ( the constant C ) the greater the rate at which time passes for your computer, so as you approach the speed of light, time will "speed up" for you.

It sounds like what you might actually be looking for is an event scheduler, where you specify that certain events must happen at specific points in simulated time and you want to be able to change the relationship between real time and simulated time (perhaps dynamically). You can run into boundary cases when you start to change the speed of time in the process of running your simulation and you may also have to deal with cases where real time takes longer to return than normal (your thread didn't get a time slice as soon as you wanted, so you might not actually be able to achieve the simulated time you're targeting.)
For instance, suppose you wanted to update your simulation at least once per 50ms of simulated time. You can implement the simulation scheduler as a queue where you push events and use a scaled output from a normal Stopwatch class to drive the scheduler. The process looks something like this:
Push (simulate at t=0) event to event queue
Start stopwatch
lastTime = 0
simTime = 0
While running
simTime += scale*(stopwatch.Time - lastTime)
lastTime = stopwatch.Time
While events in queue that have past their time
pop and execute event
push (simulate at t=lastEventT + dt) event to event queue
This can be generalized to different types of events occurring at different intervals. You still need to deal with the boundary case where the event queue is ballooning because the simulation can't keep up with real time.

I'm not entirely sure what you're looking to do (doesn't a minute always have 60 seconds?), but I'd utilize Thread.Sleep() to accomplish what you want.

Related

C# performance counter Timer100Ns. How to?

I have an application which monitors a particular event and then starts to calculate things once it happens. Events are irregular and can come in any pattern from bunches in a sec to none for long time..
I want to measure %% of time the application is busy (similar to CPU % Usage)
I want to use Timer100Ns counter
Two questions:
Do I increment it by hardware ticks or by DateTime ticks (e.g. if I use Stopwatch - do I use sw.ElapsedTicks or sw.Elapsed.Ticks) ?
Do I need a base counter for it?
so I am about to write something like this:
Stopwatch sw = new Stopwatch();
sw.Start();
// Do some operation which is irregular by nature
sw.Stop();
// Measure utilization of the application
myCounterOfTypeTimer100Ns.IncrementBy(sw.Elapsed.Ticks);
Will it do ?
EDIT : I experimented with it a bit and now its even more confusing.. It actually shows the values I increment it by. Not %%.
The mystery unravelled. It currently appears that I don't use it in the way it was supposed to be used (or rather I didn't read TFM properly). If the sampling interval is 1s (as in perf mon live window) and you intervals are more than 1s then it shows you a nonsense number... To achieve smoothness, the activity you are trying to measure must be really fractions of 1s.. Otherwise this counter is not a good idea..
The answer for this kind of problem (although its not obvious, but still disturbing that nobody suggested it in a week) is actually SampleCounter.

Get milliseconds passed

A just need a stable count of the current program's progression in milliseconds in C#. I don't care about what timestamp it goes off of, whether it's when the program starts, midnight, or the epoch, I just need a single function that returns a stable millisecond value that does not change in an abnormal manner besides increasing by 1 each millisecond. You'd be surprised how few comprehensive and simple answers I could find by searching.
Edit: Why did you remove the C# from my title? I'd figure that's a pretty important piece of information.
When your program starts create a StopWatch and Start() it.
private StopWatch sw = new StopWatch();
public void StartMethod()
{
sw.Start();
}
At any point you can query the Stopwatch:
public void SomeMethod()
{
var a = sw.ElapsedMilliseconds;
}
If you want something accurate/precise then you need to use a StopWatch, and please read Eric Lippert's Blog (formerly the Principal Developer of the C# compiler Team) Precision and accuracy of DateTime.
Excerpt:
Now, the question “how much time has elapsed from start to finish?” is a completely different question than “what time is it right now?” If the question you want to ask is about how long some operation took, and you want a high-precision, high-accuracy answer, then use the StopWatch class. It really does have nanosecond precision and accuracy that is close to its precision.
If you don't need an accurate time, and you don't care about precision and the possibility of edge-cases that cause your milliseconds to actually be negative then use DateTime.
Do you mean DateTime.Now? It holds absolute time, and subtracting two DateTime instances gives you a TimeSpan object which has a TotalMilliseconds property.
You could store the current time in milliseconds when the program starts, then in your function get the current time again and subtract
edit:
if what your going for is a stable count of process cycles, I would use processor clocks instead of time.
as per your comment you can use DateTime.Ticks, which is 1/10,000 of a millisecond per tick
Also, if you wanted to do the time thing you can use DateTime.Now as your variable you store when you start your program, and do another DateTime.Now whenever you want the time. It has a millisecond property.
Either way DateTime is what your looking for
It sounds like you are just trying to get the current date and time, in milliseconds. If you are just trying to get the current time, in milliseconds, try this:
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

More precise Thread.Sleep

How can i do Thread.Sleep(10.4166667);?
OK i see now that Sleep is not the way to go.
So i use Timer but timer is also in ms put i need more precise
Is there timer with nanosecond accuracy?
So you want your thread to sleep precisely for that time and then resume? Forget about it. This parameter tells the system to wake the Thread after at least this number of milliseconds. At least. And after resuming, the thread could be put to sleep once again in a blink of an eye. That just how Operating Systems work and you cannot control it.
Please note that Thread.Sleep sleeps as long as you tell it (not even precisely), no matter how long code before or after takes to execute.
Your question seems to imply that you want some code to be executed in certain intervals, since a precise time seems to matter. Thus you might prefer a Timer.
To do such a precise sleep you would need to use a real time operating system and you would likely need specialized hardware. Integrity RTOS claims to respond to interrupts in nanoseconds, as do others.
This isn't going to happen with C# or any kind of high level sleep call.
Please note that the argument is in milliseconds, so 10 is 10 milliseconds. Are you sure you want 10.41 etc milliseconds? If you want 10.41 seconds, then you can use 10416.
The input to Thread.Sleep is the number of milliseconds for which the thread is blocked. After that it will be runnable, but you have no influence over when it is actually scheduled. I.e. in theory the thread could wait forever before resuming execution.
It hardly ever makes sense to rely on specific number of milliseconds here. If you're trying to synchronize work between two threads there are better options than using Sleep.
As you already mentioned: You could combine DispatcherTimer with Stopwatch (Making sure the IsHighResolution and Frequency suits your needs). Start the Timer and the Stopwatch, and on discreet Ticks of the Timer check the exact elapsed time of the stopwatch.
If you are trying to rate-limit a calculation and insist on using only Thread.Sleep then be aware there is a an underlying kernel pulse rate (roughly 15ms), so your thread will only resume when a pulse occurs. The guarantee provided is to "wait at least the specified duration." For example, if you call Thread.Sleep(1) (to wait 1ms), and the last pulse was 13ms ago, then you will end up waiting 2ms until the next pulse comes.
The draw synchronization I implemented for a rendering engine does something similar to dithering to get the quantization to the 15ms intervals to be uniformly distributed around my desired time interval. It is mostly just a matter of subtracting half the pulse interval from the sleep duration, so only half the invocations wait the extra duration to the next 15ms pulse, and half occur early.
public class TimeSynchronizer {
//see https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep
public const double THREAD_PULSE_MS = 15.6d;//TODO read exact value for your system
public readonly TimeSpan Min = TimeSpan.Zero;
public TimeSynchronizer(TimeSpan? min = null) {
if (min.HasValue && min.Value.Ticks > 0L) this.Min = min.Value;
}
private DateTime _targetTimeUtc = DateTime.UtcNow;//you may wish to defer this initialization so the first Synchronize() call assuredly doesn't wait
public void Synchronize() {
if (this.Min.Ticks > 0L) {
DateTime nowUtc = DateTime.UtcNow;
TimeSpan waitDuration = this._targetTimeUtc - nowUtc;
//store the exact desired return time for the next inerval
if (waitDuration.Ticks > 0L)
this._targetTimeUtc += this.Min;
else this._targetTimeUtc = nowUtc + this.Min;//missed it (this does not preserve absolute synchronization and can de-phase from metered interval times)
if (waitDuration.TotalMilliseconds > THREAD_PULSE_MS/2d)
Thread.Sleep(waitDuration.Subtract(TimeSpan.FromMilliseconds(THREAD_PULSE_MS/2d)));
}
}
}
I do not recommend this solution if your nominal sleep durations are significantly less than the pulse rate, because it will frequently not wait at all in that case.
The following screenshot shows rough percentile bands on how long it truly takes (from buckets of 20 samples each - dark green are the median values), with a (nominal) minimum duration between frames set at 30fps (33.333ms):
I am suspicious that the exact pulse duration is 1 second / 600, since in SQL server a single DateTime tick is exactly 1/300th of a second

Clock Application

I am creating a clock application in C#.Net.I have images for each digits from 0-9. I have a timer in the main page constructor which ticks every seconds
DispatcherTimer tmr = new DispatcherTimer();
tmr.Interval = TimeSpan.FromSeconds(1);
tmr.Tick += new EventHandler(tmr_Tick);
tmr.Start();
void tmr_Tick(object sender, EventArgs e)
{
dt = DateTime.Now;
UpdateSecondsImages(dt);
}
private void UpdateSecondsImages(DateTime dt)
{
secondSource2 = dt.Second % 10;
secondDigit2.Source = digimgs[secondSource2];
if (secondSource2 == 0)
{
secondSource1 = dt.Second / 10;
secondDigit1.Source = digimgs[secondSource1];
}
if (secondSource1 == 0)
{
UpdateMinuteImages(dt);
}
}
But the problem I am facing now is this code may skip a second for a minute.Please suggest alternate way to make this smooth from a performance point of view.
Simple. When you set a timer to go off every second you are saying, "please sleep for at least 1 second before waking up and notifying me". In reality, you could be sleeping for much longer. Also, different timing APIs have clock drift relative to each other. The clock that timers are based on may not be the same clock that the DateTime.Now is based on.
Think of it like this - let's say you are actually be waking up once every 1.02 seconds.
Hence, every 50 seconds, you'll skip a beat in rendering. For example you'll go from waking up at "49.98" (rendered as "49") and then your next interval you are woken up at "51.00".
The simple workaround is to sleep for sometime less than 1 second. In your case, I suggest sleeping between 500-750 milliseconds instead of a full second. You can simply re-render the same time again in the case where you wakeup within the same second interval. Or as a trivial optimization, just do nothing when you've already woken up an the second count hasn't changed since previous time.
try saying:
tmr.Interval = TimeSpan.FromMilliSeconds(500);
If it's okay to show clock only when they're visible, I'd rather suggest to use CompositionTarget.Render event handler. Get current time in it and update the UI appropriately. This will not only eliminate the error but will let you render milliseconds as well :).
I highly doubt this approach impacts performance (cos() and sin() are damn fast in our days). But even if it will (you are rendering thousands of clocks), you can update UI not on every frame.
Hope this helps.
Yesterday we launched a contest with Ball Watch USA to create watches in Silverlight. I recommend using a Storyboard to rotate the second hand 360 degrees over 1 minute and set the storyboard to repeat forever. Here are some links:
The Contest
A video describing the task
The animation XAML in SL1
Updating the code to SL2

DispatcherTimer eating up CPU over time causing WPF visual not rendering properly

I have a WPF app that uses DispatcherTimer to update a clock tick.
However, after my application has been running for approx 6 hours the clocks hands angles no longer change. I have verified that the DispatcherTimer is still firing with Debug and that the angle values are still updating, however the screen render does not reflect the change.
I have also verified using WPFPerf tools Visual Profiler that the Unlabeled Time, Tick (Time Manager) and AnimatedRenderMessageHandler(Media Content) are all gradually growing until they are consuming nearly 80% of the CPU, however Memory is running stable.
The hHandRT.Angle is a reference to a RotateTransform
hHandRT = new RotateTransform(_hAngle);
This code works perfectly for approx 5 hours of straight running but after that it delays and the angle change does not render to the screen. Any suggestions for how to troubleshoot this problem or any possible solutions you may know of.
.NET 3.5, Windows Vista SP1 or Windows XP SP3 (both show the same behavior)
EDIT: Adding Clock Tick Function
//In Constructor
...
_dt = new DispatcherTimer();
_dt.Interval = new TimeSpan(0, 0, 1);
_dt.Tick += new EventHandler(Clock_Tick);
...
private void Clock_Tick(object sender, EventArgs e)
{
DateTime startTime = DateTime.UtcNow;
TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById(_timeZoneId);
_now = TimeZoneInfo.ConvertTime(startTime, TimeZoneInfo.Utc, tst);
int hoursInMinutes = _now.Hour * 60 + _now.Minute;
int minutesInSeconds = _now.Minute * 60 + _now.Second;
_hAngle = (double)hoursInMinutes * 360 / 720;
_mAngle = (double)minutesInSeconds * 360 / 3600;
_sAngle = (double)_now.Second * 360 / 60;
// Use _sAngle to showcase more movement during Testing.
//hHandRT.Angle = _sAngle;
hHandRT.Angle = _hAngle;
mHandRT.Angle = _mAngle;
sHandRT.Angle = _sAngle;
//DSEffect
// Add Shadows to Hands creating a UNIFORM light
//hands.Effect = textDropShadow;
}
Along the lines of too much happening in the clock tick, I'm currently trying this adjustment to see if it helps. Too bad it takes 5 hours for the bug to manifest itself :(
//DateTime startTime = DateTime.UtcNow;
//TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById(_timeZoneId);
//_now = TimeZoneInfo.ConvertTime(startTime, TimeZoneInfo.Utc, tst);
_now = _now.AddSeconds(1);
You say you're creating an instance of the Clock class each time? Note that timers in .NET will root themselves to keep themselves from being garbage collected. They'll keep on firing until you stop them yourself, and they will keep your Clock objects alive because they are referenced in the timer tick event.
I think what's happening is that with each Clock you create you start another timer. At first you only fire 1 event per second, but then you get add on another timer and get 2 per second, and they continue to accumulate in this way. Eventually you see your Tick handler and AnimatedRenderMessageHandler rising in CPU until they bog down and are unable to update your screen. That would also explain why increasing the frequency of the timer firings made your symptoms appear sooner.
The fix should be simple: just stop or dispose the DispatcherTimer when you are done with your Clock object.
You're assuming it's the DispatcherTimer and focusing totally on that. I personally have a hard time believing it has anything to do with the timer itself, but rather think it has to do with whatever you're doing within the timer tick. Can you tell us more about exactly what is going on each time the timer ticks?
hHandRT.Angle = _hAngle;
mHandRT.Angle = _mAngle;
sHandRT.Angle = _sAngle;
I believe you have to look at your above code once again.
You are setting Angle property of your transform for all 3 transforms even if you dont need them to change every second. Your minute will change for every 60 changes and your hour will change for every 3600 seconds. However you can atleast reduce your changing hours angle for every second.
What is happening here is, whenever you request transform changes to WPF, WPF queues the request to priority dispatch queue and every second you are pushing more changes to be done then it can process. And this is the only reason your CPU usage keeps on increasing instead of memory.
Detailed Analysis:
After looking at your code, I feel your DispatcherTimer_Tick event does too much of calculation, remember Dispatcher thread is already overloaded with lots of things to do like managing event routing, visual update etc, if keep your cpu more busy to do custom task in dispatcher thread that too in every second event, it will definately keep on increasing the queue of pending tasks.
You might think its a small multiplication calculation but for Dispatcher thread it can be costly when it comes to loading timezones, converting time value etc. You should profile and see the tick execution time.
You should use System.Threading.Timer object, that will run on another thread, after every tick event, when you are done with your calculations of final angles required, you can then pass them on to Dispatcher thread.
like,
Dispatcher.BeginInvoke((Action)delegate(){
hHandRT.Angle = _hAngle;
mHandRT.Angle = _mAngle;
sHandRT.Angle = _sAngle;
});
By doing this, you will be reducing workload from dispatcher thread little bit.

Categories

Resources