private void DoWork() { /* Check frozen. */ if (FreezableClock.IsFrozen && !_pausedEvent.WaitOne()) { return; } var now = ProgramTime; /* Do sleep waiting while greater than 2 x sleep period */ var sleepWaitPeriod = SleepWaitPeriod; if (sleepWaitPeriod.Ticks > 0) { while (!_stageSkipped.Value && FreezableClock.Unit.ConvertTo((long)(_nextUpdateTime - now), TimeUnit.Tick) > sleepWaitPeriod.Ticks * 2) { Thread.Sleep(sleepWaitPeriod); now = ProgramTime; } } /* Do busy waiting while less than 2 x sleep period */ while (now < _nextUpdateTime && !_stageSkipped.Value) { if (FreezableClock.IsFrozen) { return; /* Exit busy waiting while paused */ } now = ProgramTime; } /* Actual processing procedures */ do { /* Reset skip state */ _stageSkipped.Reset(); /* Get next stage, exit on null (END REACHED) */ Stage stage = null; try { for (;;) /* Loop only for skip */ { stage = _stageProvider.Next(); now = ProgramTime; var eventArgs = new StageChangedEventArgs(now, stage); StageChanged?.Invoke(this, eventArgs); if (stage == null) { eventArgs.Action = StageAction.Terminate; } switch (eventArgs.Action) { case StageAction.Terminate: /* Terminate entire program */ goto StopProgram; case StageAction.Skip: /* Skip current stage directly */ continue; case StageAction.Pause: /* Pause at the start of the stage */ Pause(); goto BreakOuterLoop; default: /* Accepted */ goto BreakOuterLoop; } BreakOuterLoop: break; } } catch (ThreadAbortException) { throw; } /* Aborted by stopping underlying runner */ catch (Exception e) /* Process unhandled exception */ { var eventArgs = new ExceptionEventArgs(e); UnhandledException?.Invoke(this, eventArgs); if (!eventArgs.Handled) { throw new Exception("Unhandled exception", e); } } /* Update time */ if (stage != null) { _nextUpdateTime = now + stage.Duration; } continue; /* Stop */ StopProgram: Stop(); return; } while (now >= _nextUpdateTime || _stageSkipped.Value); /* Check if need to move next */ }