private void Loop(CancellationToken cancellationToken) { const double targetFps = 120; var lastTimeFrame = applicationStopwatch.ElapsedTime; var waitHandle = new AutoResetEvent(false); redrawnEvent.WaitOne(); app.Load(); while (!cancellationToken.IsCancellationRequested) { TimeSpan time = applicationStopwatch.ElapsedTime; TimeSpan diff = time - lastTimeFrame; if (dispatcher is IUpdatable updatable) { updatable.Update(time, diff); } updatablesService.Update(time, diff); app.Update(time, diff); dispatcher.GetIsContentInvalid(true, out var shouldRedraw); TimeSpan newTime = applicationStopwatch.ElapsedTime; diff = newTime - time; int msToWait = Math.Max(1, (int)(1000.0 / targetFps - diff.TotalMilliseconds)); if (shouldRedraw) { RenderRequest(); redrawnEvent.WaitOne(); } else { waitHandle.WaitOne(msToWait); } lastTimeFrame = time; } }