/// <summary> /// Determines whether the specified calculation is cancelling. /// </summary> /// <param name="calculationId">The calculation identifier.</param> /// <returns> /// <c>true</c> if the specified calculation identifier is cancelling; otherwise, <c>false</c>. /// </returns> public bool IsCancelling(int calculationId) { return(calculationDepot.HasState(calculationId, State.NameCancelling)); }
/// <summary> /// Dispatches a calculation and sets its state to running. /// </summary> /// <param name="circleChunkSize">Size of the circle chunk.</param> public void Dispatch(int circleChunkSize) { var calculation = calculationService.GetFirstByState(State.NameEnqueued); var stateCancelling = stateDepot.GetByName(State.NameCancelling); Timer cancellingTimer = null; CancellationTokenSource cts = new CancellationTokenSource(); try { if (calculation == null) { return; } var runningCalculation = calculationService.GetFirstByState(State.NameRunning); if (runningCalculation != null) { App.Logger.Info($"Calculation with state {State.NameEnqueued} found but already a calculation in state {State.NameRunning}."); return; } cancellingTimer = new Timer((t) => { if (calculationDepotTimer.HasState(calculation.Id, State.NameCancelling)) { // Cancel Task and stop timer cts.Cancel(); cancellingTimer.Dispose(); } }, null, App.Config.CancellationCheckInterval, App.Config.CancellationCheckInterval); DispatchCalculation(calculation, cts.Token, circleChunkSize); } catch (AggregateException ex) { // Parallel Loop throws Aggregate Exception if (ex.InnerExceptions.Any(x => x is OperationCanceledException)) { Cancel(calculation); } } catch (OperationCanceledException) { Cancel(calculation); } catch (Exception) { var stateError = stateDepot.GetByName(State.NameError); calculation.StateId = stateError.Id; throw; } finally { if (calculation != null) { calculation.EndDate = DateTime.Now; calculationDepot.Save(calculation); } if (cancellingTimer != null) { cancellingTimer.Dispose(); } } }