/// <summary> /// Implements worker control, execution and delay logic in a loop. /// </summary> private void RunWorkerLoop() { while (WorkerState != WorkerState.Stopped && !IsDisposing && !IsDisposed) { CycleStopwatch.Restart(); var interruptToken = CycleCancellation.Token; var period = Period.TotalMilliseconds >= int.MaxValue ? -1 : Convert.ToInt32(Math.Floor(Period.TotalMilliseconds)); var delayTask = Task.Delay(period, interruptToken); var initialWorkerState = WorkerState; // Lock the cycle and capture relevant state valid for this cycle CycleCompletedEvent.Reset(); // Process the tasks that are awaiting if (ProcessStateChangeRequests()) { continue; } try { if (initialWorkerState == WorkerState.Waiting && !interruptToken.IsCancellationRequested) { // Mark the state as Running WorkerState = WorkerState.Running; // Call the execution logic ExecuteCycleLogic(interruptToken); } } catch (Exception ex) { OnCycleException(ex); } finally { // Update the state WorkerState = initialWorkerState == WorkerState.Paused ? WorkerState.Paused : WorkerState.Waiting; // Signal the cycle has been completed so new cycles can be executed CycleCompletedEvent.Set(); if (!interruptToken.IsCancellationRequested) { var cycleDelay = ComputeCycleDelay(initialWorkerState); if (cycleDelay == Timeout.Infinite) { delayTask = Task.Delay(Timeout.Infinite, interruptToken); } ExecuteCycleDelay( cycleDelay, delayTask, CycleCancellation.Token); } } } ClearStateChangeRequests(); WorkerState = WorkerState.Stopped; }
/// <summary> /// Executes the worker cycle control logic. /// This includes processing state change requests, /// the exeuction of use cycle code, /// and the scheduling of new cycles. /// </summary> private void ExecuteWorkerCycle() { CycleStopwatch.Restart(); lock (SyncLock) { if (IsDisposing || IsDisposed) { WorkerState = WorkerState.Stopped; // Cancel any awaiters try { StateChangedEvent.Set(); } catch { /* Ignore */ } return; } // Prevent running another instance of the cycle if (CycleCompletedEvent.IsSet == false) { return; } // Lock the cycle and capture relevant state valid for this cycle CycleCompletedEvent.Reset(); } var interruptToken = CycleCancellation.Token; var initialWorkerState = WorkerState; // Process the tasks that are awaiting if (ProcessStateChangeRequests()) { return; } try { if (initialWorkerState == WorkerState.Waiting && !interruptToken.IsCancellationRequested) { // Mark the state as Running WorkerState = WorkerState.Running; // Call the execution logic ExecuteCycleLogic(interruptToken); } } catch (Exception ex) { OnCycleException(ex); } finally { // Update the state WorkerState = initialWorkerState == WorkerState.Paused ? WorkerState.Paused : WorkerState.Waiting; lock (SyncLock) { // Signal the cycle has been completed so new cycles can be executed CycleCompletedEvent.Set(); // Schedule a new cycle ScheduleCycle(!interruptToken.IsCancellationRequested ? ComputeCycleDelay(initialWorkerState) : 0); } } }