/// <summary> /// Signals to start a new execution at the next available slot. /// </summary> protected void QueueExecution() { lock (_syncExecution) { if (!this.IsLoaded || this.IsStopped) { throw new InvalidOperationException("Cannot execute. Service app is not loaded or has stopped."); } bool createContext = false; switch (this.ExecutionMode) { case ExecutionMode.Default: case ExecutionMode.Idempotent: if (!this._executionContexts.Any() || this._executionContexts.All(c => c.Failed)) { createContext = true; } break; case ExecutionMode.Inline: createContext = true; break; case ExecutionMode.Concurrent: if (Settings.MaxConcurrentExecutions == 0 || this._executionContexts.Count(c => c.IsExecuting) <= Settings.MaxConcurrentExecutions) { createContext = true; } break; default: throw new NotImplementedException("Execution mode not yet implemented"); } if (createContext) { var context = new ServiceAppContext() { Failed = false, QueuedTime = DateTimeResolver.Resolve(), Guid = Guid.NewGuid().ToString(), Name = this.DisplayName }; this._executionContexts.Add(context); } } }
/// <summary> /// Handles the 'tick' event of the executionTimer. /// </summary> /// <param name="state">The state.</param> private void ExecutionTimer_Tick(object state) { if (this.IsStopped) { _executionTimer.Change(Timeout.Infinite, Timeout.Infinite); return; } ServiceAppContext currentContext = null; switch (this.ExecutionMode) { case Execution.ExecutionMode.Default: case Execution.ExecutionMode.Idempotent: case Execution.ExecutionMode.Concurrent: currentContext = this._executionContexts.FirstOrDefault(c => c.CanExecute); break; case Execution.ExecutionMode.Inline: currentContext = this._executionContexts.FirstOrDefault(c => c.CanExecute && !this.IsExecuting); break; default: throw new NotImplementedException("Execution mode not yet implemented"); } if (currentContext != null) { Task executionTask = Task.Run(() => { Messages.WriteState(Enums.State.Executing); Messages.WriteDebug("Starting exection for {0}. Time: {1}", this.DisplayName, currentContext.StartTime); currentContext.StartTime = DateTimeResolver.Resolve(); Messages.WritePerformance(currentContext); try { this.Execute(ref currentContext); Messages.WriteState(Enums.State.Idle); } catch (Exception e) { currentContext.Failed = true; currentContext.CustomMessage = e.Message; this.HandleException(e, false); Messages.WriteState(Enums.State.Failed); } finally { currentContext.EndTime = DateTimeResolver.Resolve(); Messages.WriteDebug("Ended exection for {0}. Duration: {1}", this.DisplayName, currentContext.Duration); Messages.WritePerformance(currentContext); } this._executionContexts.Remove(currentContext); }); currentContext.Handle = executionTask; } this.CleanUpServiceAppContexts(); this.CheckParentProcessAlive(); }