I've inserted a variable of type Double in the application/settings file and I'm using a "while" loop to do a small calculation:
double final=0;
double cost = application.settings.default.cost; // 0.15
while(true)
{
Thread.Sleep(1000); //speeded up version of 60000 (1 minute)
final+=cost;
//code that waits for the user to quit the loop
}
the result after 1 hour should be 9.00 but it's calculating to something like 24.00 :/
however, if I hardcode the value in to the code, I get the desired result of 9.00
double final=0;
double cost = 0.15
while(true)
{
Thread.Sleep(1000); //speeded up version of 60000 (1 minute)
final+=cost;
//code that waits for the user to quit the loop
}
Any ideas?
Thread.Sleep(1000); does not mean that your code is executed exactly every second.
If you run your code this way 10 times for 1 hour you will get 10 different results.
This was discussed here as well:
How accurate is Thread.Sleep(TimeSpan)?
(although there Thread.Sleep is used with a TimeSpan. The main issue stays the same)
Edit:
I don't know what exactly your are calculating. But calculating costs in this way is not a good approach as it is very inaccurate.
Better take a timestamp when you start calculating your costs and take another one when you are finished. Take the difference of both timestamps and you can calculate the costs quite accurately. Your method gets more and more inacurrate the longer your code us running.
Related
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;
This question is about System.Threading.Thread.Sleep(int). I know there is no method for a decimal value, but I really need to work with decimals.
I have a device which takes 20.37 milliseconds to turn by 1 degree. So, I need to put the code to sleep for an appropriate multiplication of 20.37 (2 degrees = 20.37*2 etc). Since the thread class got no decimal sleep method, how can I do this?
That does not work that way. Sleep will grant you that the thread sats idle for x time, but not that it won't stay idle for more. The end of the sleep period means that the thread is available for the scheduler to run it, but the scheduler may chose to run other threads/processes at that moment.
Get the initial instant, find the final instant, and calculate the current turn by the time passed. Also, do not forget to check how precise the time functions are.
Real-time programming has some particularities in its own as to advice you to seek for more info in the topic before trying to get something to work. It can be pretty extensive (multiprocessing OS vs monoprocessing, priorities, etc.)
Right, as pointed out in the comments, Thread.Sleep isn't 100% accurate. However, you can get it to (in theory) wait for 20.27 milliseconds by converting the milliseconds to ticks, and then making a new TimeSpan and calling the method with it, as follows:
Thread.Sleep(new TimeSpan(202700))
//202700 is 20.27 * TimeSpan.TicksPerMillisecond (which is 10,000)
Again, this is probably not going to be 100% accurate (as Thread.Sleep only guarantees for AT LEAST that amount of time). But if that's accurate enough, it'll be fine.
You can simply divide the integer - I just figured that out.
I needed less than a milisecond of time the thread sleeps so I just divided that time by an integer, you can either define a constant or just type in:
System.Threading.Thread.Sleep(time / 100);
Or what number you want.
Alternatively, as mentioned, you can do it like:
int thisIsTheNumberYouDivideTheTimeBy = 100;
Thread.Sleep(time / thisIsTheNumberYouDivideTheTimeBy);
Its actually quite simple. Hope that helped.
By the way, instead of
System.Threading.Thread.Sleep(x);
you can just type
Thread.Sleep(x);
unless you haven't written
using System.Threading;
in the beginning.
I had the same problem. But as a work around, i substitute the float vslie but convert to int value in the passing. The code itself rounds off for me and the thread sleeps for that long. As i said, its a work around and i'm just saying, not that it's accurate
You can use little bit of math as a workaround.
Let´s assume, that you don´t want to be extremely precise,
but still need overall float precise sleep.
Thread.Sleep(new Random().Next(20,21));
This should give you ~20.5 sleep timing. Use your imagination now.
TotalSleeps / tries = "should be wanted value", but for single sleep interval, this will not be true.
Dont use new Random() make an instance before.
I'm using the WMP (AxWindowsMediaPlayer) in a C# project and would like to extract the exact time stamp up to 0.1 or 0.01 seconds. Is there any way how to accomplish that?
The following won't work as it's too imprecise :-/
player.Ctlcontrols.currentPositionString
I don't think that having a timer running simultaneously is a good solution because I would have to stop and resume it every time the user pauses the video, and it will eventually become wrong after a few pauses and resumes.
Have you tried using the currentPosition property which returns a double in seconds from start instead of the currentPositionString which returns a string MM:ss format.
The string format will only give you precision to the closest integer value of the second. The currentPosition property which is a double should be giving you fractions of a second.
References
currentPositionString http://msdn.microsoft.com/en-us/library/windows/desktop/dd564739(v=vs.85).aspx
currentPosition http://msdn.microsoft.com/en-us/library/windows/desktop/dd564740(v=vs.85).aspx
I have a code snippet like this:
while(true)
{
myStopWatch.Start();
DoMyJob();
myStopWatch.Stop();
FPS = 1000/myStopWatch.Elapsed.ToMillionSeconds();
myStopWatch.Reset();
}
which works pretty good, I got the FPS around 100(+/-2). But sometimes I just want to focus on a certain part of the DoMyJob() performance and add some feedbacks, so I split the DoMyJob() to DoMyJob1() and add DoMyJobs2(). the first part is mainly calculation stuff, second part is to visualize the calculation on the Form and update some indicators.
So the code becomes:
while(true)
{
myStopWatch.Start();
DoMyJob_1();
myStopWatch.Stop();
FPS = 1000/myStopWatch.Elapsed.ToMillionSeconds();
myStopWatch.Reset();
DoMyJob_2();
}
I did not expect anything would mess up the FPS since DoMyJob1 is almost the same as the original DoMyJob. But oops..it messed up. the FPS becomes frenzy, bouncing between 40 and up to 600 in a somehow random manner. I wiped out the DoMyJob2() and FPS went back to steady 100.
As I examined deep into the FPS sequence, I found out the FPSs are not random at all - they had like 4 or 5 different ranges, in my code, 30-50, 100-120, 300-360, 560-600, etc. Not a single number falls into the gaps. Then I tried the code in another laptop and the issue still exists, but just with different ranges. I know StopWatch uses Win32API. Is it because it's buggy and I run the code on the 64bit system??
BTW: what the best way to measure FPS on .NET Windows Form App? (like if FPS=100 or more)
If DoMyJob_2 takes a variable amount of time, then you have a slice of time from every second that is not being taken into account. You could use your method to calculate an average time to execute DoMyJob_1, but not to determine frames per second. For example:
loop 1:
task 1: 5ms
reported fps: 1000/5ms = 200
task 2: 15ms
real fps: 1000/20ms = 50
loop 2:
task 1: 5ms
reported fps: 1000/5ms = 200
task 2: 25ms
real fps: 1000/30ms = 33
...
So I'm not sure that's what you are seeing, but it seems possible. What you are describing (fluctuating reported fps) might actually make more sense if the total length of the job tends to be stable, but the way you split the job makes each part variable.
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