Reputation: 746
So for a project of mine I need to fetch values from a piece of hardware every 100 ms. The fetching takes x amount of milliseconds. So what I'm looking for but cannot find is a way to make sure a for/while always takes 100 ms (or more).
So in pseudo code:
for (int i = 0; i < 100; i++) // Take measurements for 10 seconds
{
// Call some async method that sleeps for 100 ms
this.temperatureList.Add(this.HardwareManager.GetSensorValue(ESensor.Temperature)); // Takes 15 ms
this.temperatureList.Add(this.HardwareManager.GetSensorValue(ESensor.Pressure)); // Takes 30 ms
// await async method to finish
}
I have tried some async await things with this but I cannot seem to comprehend it. Anyone who can help me find a reliable way to get 10 seconds of measurements with an interval of 100 ms?
EDIT: I know that since I'm running C# on Windows, timing is not really a valid option. But this does not really matter in my question. My question is, how can I make sure the for loop takes at least(!!!) a 100 ms, while being as close as possible to 100 ms.
Upvotes: 4
Views: 1841
Reputation: 391276
One way of doing it would be to create a Stopwatch and just wait for it to reach the next milestone after doing each operation.
The benefit of this way is that:
Sort of like this:
var sw = Stopwatch.StartNew();
long next = 100;
while (sw.ElapsedMilliseconds < 10000)
{
// do your operation here
long left = next - sw.ElapsedMilliseconds;
if (left > 0)
await Task.Delay((int)left);
next += 100;
}
Due to the accuracy of things, your operations will around each 100 milliseconds, but they shouldn't drift.
If you're OK with tying up a thread for the duration of those 10 seconds, you could switch out the delay part with Thread.Sleep
:
if (left > 0)
Thread.Sleep((int)left);
It will run your operations closer to the 100 millisecond mark, but might still have a slight overhead due to the fact that Thread.Sleep
has some overhead as well.
If you're OK with "burning CPU", you can do this instead:
var sw = Stopwatch.StartNew();
var next = 100;
while (sw.ElapsedMilliseconds < 10000)
{
// do your operation here
while (sw.ElapsedMilliseconds < next) ;
next += 100;
}
This will run your operation even closer to the actual 100 milliseconds mark, as Task.Delay
and Thread.Sleep
will have overhead that will tend to delay just slightly longer than what you intended. It will, however, tie up a CPU core for the duration of those 10 seconds.
Upvotes: 7