using System; using System.Threading; namespace ScreenConnect; public abstract class ThreadRunner(CorePriority priority, bool rerunOnException, bool crashOnException) : ThreadRunnerBase where TThreadRunContext : ThreadRunContext { private ContextHolder runContextHolder = new ContextHolder(); private RunStatus status; protected object SyncLock => runContextHolder.SyncLock; public bool IsRunning => status == RunStatus.Running; public override void EnsureRunState(bool running, bool waitForState = true) { lock (SyncLock) { bool flag = false; while ((!running || status != RunStatus.Running) && (running || status != RunStatus.Stopped) && (!running || status != RunStatus.Starting || waitForState) && (running || status != RunStatus.Stopping || waitForState) && !((running && status == RunStatus.Stopped) & flag)) { if (running && status == RunStatus.Stopped) { flag = true; status = RunStatus.Starting; OnStarting(); Singleton.Instance.StartThread(GetType().GetMoreFriendlyName(), priority, RunThread, null); Monitor.PulseAll(SyncLock); } else if (!running && (status == RunStatus.Starting || status == RunStatus.Running)) { runContextHolder.CurrentContext?.SignalOutOfBandShutdown(); status = RunStatus.Stopping; Monitor.PulseAll(SyncLock); if (!waitForState) { break; } } else { Monitor.Wait(SyncLock); } } } } public abstract TThreadRunContext CreateThreadRunContext(object syncLock); private void RunThread(object state) { bool flag = false; lock (SyncLock) { if (status == RunStatus.Starting) { flag = true; status = RunStatus.Running; Monitor.PulseAll(SyncLock); } } if (!flag) { return; } OnStarted(); bool flag2 = false; while (true) { try { flag2 = false; TThreadRunContext currentContext; using (runContextHolder.WithNewContext(() => CreateThreadRunContext(SyncLock), out currentContext)) { RunThread(currentContext); } } catch (Exception ex) { OnUnexpectedExceptionOccurred(ex); flag2 = true; TypeTrace.TraceException(ex); if (crashOnException) { throw; } if (!rerunOnException) { break; } continue; } break; } flag2 |= status == RunStatus.Running; if (flag2) { lock (SyncLock) { status = RunStatus.Stopping; Monitor.PulseAll(SyncLock); } } lock (SyncLock) { status = RunStatus.Stopped; Monitor.PulseAll(SyncLock); } OnStopped(flag2); } protected abstract void RunThread(TThreadRunContext runContext); } public abstract class ThreadRunner : ThreadRunner { protected ThreadRunner(CorePriority priority, bool rerunOnException, bool crashOnException) : base(priority, rerunOnException, crashOnException) { } public override ThreadRunContext CreateThreadRunContext(object syncLock) { return new ThreadRunContext(syncLock); } }