In my C# script, I have a C# function that I have to execute exactly every 50ms for 20 seconds. I am doing this with a C# microtimer dll.
https://www.codeproject.com/Articles/98346/Microsecond-and-Millisecond-NET-Timer
But execution of the function takes, depending on network conditions, sometimes >50 ms (longer than timer period). In order to check how often this problem occurs, I have placed a counter in the Microtimer function. If , after 20 seconds the counter value is 400, then I assume that all the 400 executions of the functions were < 50msn, that means in time.
But sometimes, after 20 seconds I get counter values greater than 400. First I couldn't understand why, but I think if the function isn't finished in 50 ms, the function is started once more in parallel, when the timer "ticks" again, so the counter value is rising once more.
Now my questions:
Is my assumption correct for the case counter values > 400?
In case of the execution of the function takes > 50ms: How can I prevent that the function is fired once more in parallel, before the previous function completed? In such cases if the execution of the function is let's say <60 msn, I want to tolerate this , and start the next function execution, when the delayed function is finished. But the general rule of executing the function every 50 ms should be kept.
How can I do this?
This is my code
public async void OnTimedEvent_MicroTimer(object sender, MicroLibrary.MicroTimerEventArgs timerEventArgs)
{
object microcount;
if (Measuring_period_finished == false) // the finished signal is coming from another timer
{
Counter += 1;
Periodic_funciton();
}
if (Measuring_period_finished == true)
{
if( Counter > 400)
{
delayed_functions=Counter-400;
message="function executed "+delayed_functions.toString()+" times delayed";
}
if( Counter == 400);
{
message="function executed always in time";
}
}
}
Is my assumption correct for the case counter values > 400?
I would expect exactly 400 invocations, regardless of how long each invocation takes. The normal behavior for non-UI timers is to run the event on a background thread, and this will allow multiple invocations to overlap. But I'm not sure about the behavior for your specific library.
In case of the execution of the function takes > 50ms , How can I prevent that the function is fired once more in parallel, before the previous function completed? In such cases if the execution of the function is let's say <60 msn, I want to tolerate this , and start the next function execution, when the delayed function is finished. But the general rule of executing the function every 50 ms should be kept.
There are several approaches. The simplest way would be to take a lock while running the method, but this would cause invocations to "queue up", this queue will be unordered if that matters.
If you used a Threading.Timer you could set the time to trigger once, measure the time your method actually take using a stopwatch, and use the elapsed time to compute the remaining time until the next tick, and reset the timer.
Or you could use a periodic timer in a loop, but I think this will skip invocations if the method runtime exceeds the period:
while (await myPeriodicTimer.WaitForNextTickAsync())
{
// your method
}
Note that both Threading.Timer and periodic timer has a max precision of 15.6ms by default. This limit applies to just about every type of non spinning wait. You can set a higher frequency, but that is a system wide change. Or you may be able to use the multimedia timer to do the same thing.
Another option would be to just write your own spin wait loop and run your method inside this loop. I.e. use a stopwatch to measure the time, and just loop until this exceeds your period. But this will burn CPU time, so would not be my preferred solution.