protected void WorkerThreadFrameDispatcher(SynchronizationContext uiThreadSyncContext) { Threading.ResetThread(Thread.CurrentThread.ManagedThreadId); try { stopWatch = System.Diagnostics.Stopwatch.StartNew(); tick = 0; prevUpdateTime = DateTime.Now; while (!cts.IsCancellationRequested) { // either use UI thread to render one frame or this worker thread bool pauseThread = false; if (RenderOnUIThread) { uiThreadSyncContext.Send((s) => { pauseThread = RunIteration(cts.Token); }, null); } else { pauseThread = RunIteration(cts.Token); } if (pauseThread) { _waitForPausedStateProcessed.Set(); _waitForMainGameLoop.WaitOne(); // pause this thread } } } catch (Exception ex) { Log.Error("AndroidGameView", ex.ToString()); } finally { bool c = cts.IsCancellationRequested; cts = null; if (glSurfaceAvailable) { DestroyGLSurface(); } if (glContextAvailable) { DestroyGLContext(); ContextLostInternal(); } lock (_lockObject) { _internalState = InternalState.Exited_GameThread; } } }
// Return true to trigger worker thread pause bool RunIteration(CancellationToken token) { // set main game thread global ID Threading.ResetThread(Thread.CurrentThread.ManagedThreadId); InternalState currentState = InternalState.Exited_GameThread; lock (_lockObject) { currentState = _internalState; } switch (currentState) { // exit states case InternalState.Exiting: // when ui thread wants to exit processStateExiting(); break; case InternalState.Exited_GameThread: // when game thread processed exiting event lock (_lockObject) { _waitForExitedStateProcessed.Set(); cts.Cancel(); } break; // pause states case InternalState.Pausing_UIThread: // when ui thread wants to pause processStatePausing(); break; case InternalState.Paused_GameThread: // when game thread processed pausing event // this must be processed outside of this loop, in the new task thread! return(true); // trigger pause of worker thread // other states case InternalState.Resuming_UIThread: // when ui thread wants to resume processStateResuming(); // pause must wait for resume in case pause/resume is called in very quick succession lock (_lockObject) { _waitForResumedStateProcessed.Set(); } break; case InternalState.Running_GameThread: // when we are running game processStateRunning(token); break; case InternalState.ForceRecreateSurface: processStateForceSurfaceRecreation(); break; // default case, error default: processStateDefault(); cts.Cancel(); break; } return(false); }