I need to implement an update loop in C# similar to an update loop in a game engine which periodically executes a sequence of tasks. I already searched for some documentation googling around and reading some SO discussions and THIS from game programming patterns, however my situation may be a little different and I didn't really found a solution to my problem. Here's my situation:
1- The update loop must process its tasks up to 1000 times per second (1000 is not an hard constraint, if the loop runs 999 or 1001 it would be fine anyway)
2- Tasks are synchronous, so if I have task1 that requires 100 seconds to execute, task2 will wait 100 seconds
3- The program executes only on Windows, so If needed I can use PInvoke to call Windows native functions
4- It's ok if the thread that starts the loop is the same that executes it and stays blocked inside it
5- The loop must not consume the entire core if there are no jobs to do or if the jobs can be processed faster than 1000 times per second. Basically the loop can sleep / wait if it needs to (more on this later)
I found here HERE a solution which implements an event loop in C#, however tasks there are asynchronous and it violates point 2.
I also found HERE a solution which uses System.Timers.Timer to execute a task.
HOWEVER:
Windows is not a realtime OS and timers have a frequency of about 15ms by default, which means about just 66 updates per second.
I know from HERE that timers can be set to 1ms, but since the setting is global it can create problems with other programs and if possible i would like to avoid this.
Finally I saw HERE that I can use Windows message pump to fire my updates using the Idle event, but I didn't found if it can be fired up to 1000 times or if it has side effects like generating garbage.
So far I have thought about these "solutions" (that are not valid since they violate points 1 or 5)
while(isRunning)
{
startTime = stopWatch.Elapsed;
ProcessTasks();
Thread.sleep(timeToWait - (stopWatch.Elapsed - startTime)); //variant below
}
But since the default minimum sleep time is about 15ms (or far more than 1ms anyway) Thread.sleep can't be used, so i tried
while ((stopTicks = this.stopWatch.ElapsedTicks - startTicks) < this.sleepTicks)
{
Thread.SpinWait(x); //OR Thread.Yield();
}
Where x is a variable that ensures enough precision and using constants inside Timespan struct I can convert ticks in milliseconds or another time unit and make the loop execute 1000 times per second. However this approach ends up consuming an entire core (100% core usage) which is bad since this code may run on battery powered laptops and in general it doesn't seem clean to me (but I may be wrong on the "clean" statement). The code is also a simplification of the real code.
So this is my situation, any ideas or am I missing something?
Also: another thing I noticed is that game engines like Unreal, Unity3d etc manage to get more than 66fps (so sleeping/waiting less than 15ms) while at the same time not consuming an entire core if it's not needed. Of course their core is mainly written in C++ and not C#, but how do they do that?
Many thanks