// Updated to do all calculations in this worker thread and to do UI updates that happen inside of this on the UI thread public void RunSimFrame(ThreadPoolTimer tpt) { const double tick = 1.0 / FrameRate; // UI seconds const int reportingInterval = 10 * (int)FrameRate; // Added check to see if the previous frame is still calculating/rendering when this method gets called by the timer // Sufficiently large scenarios (size varies depending on the PC) can take longer than a frame tick to run // When this happens a frame is dropped and we wait until the next tick to check again // Waiting an entire frame also gives the XAML/UWP rendering tasks time to finish before they are fired again // The amount of rendering work is proportional to the amount of calculation work, so this all works out if (frameInProgress) { framesDropped++; } else { frameInProgress = true; sim.Step(tick, simRunning); frameInProgress = false; framesRendered++; if ((framesRendered % reportingInterval) == 0) { Debug.WriteLine("Frames rendered = {0}, dropped = {1}, dropped pct = {2:F2}", framesRendered, framesDropped, 100.0 * (float)framesDropped / (float)(framesRendered + framesDropped)); } } }