using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Core; using Tango.Scripting.Basic; namespace Tango.FSE.Procedures { public class ProjectRunner : ExtendedObject { private ProjectSession _currentSession; public event EventHandler StateChanged; private ProjectRunnerState _state; public ProjectRunnerState State { get { return _state; } private set { _state = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(IsRunning)); RaisePropertyChanged(nameof(IsCompiling)); RaisePropertyChanged(nameof(CanRun)); RaisePropertyChanged(nameof(CanCompile)); StateChanged?.Invoke(this, value); } } public bool IsRunning { get { return State == ProjectRunnerState.Running; } } public bool IsCompiling { get { return State == ProjectRunnerState.Compiling; } } public bool CanCompile { get { return State != ProjectRunnerState.Running && State != ProjectRunnerState.Compiling; } } public bool CanRun { get { return State != ProjectRunnerState.Running && State != ProjectRunnerState.Compiling; } } public ProcedureProject Project { get; private set; } public ProjectRunner(ProcedureProject project) { Project = project; } public async Task Compile() { try { State = ProjectRunnerState.Compiling; if (Project.Inputs.GroupBy(x => x.Key).Any(x => x.Count() > 1)) { throw new InvalidOperationException("Project inputs contain duplicate keys."); } var result = await Project.Compile(); State = ProjectRunnerState.None; return result; } catch (Exception) { throw; } finally { State = ProjectRunnerState.None; } } public async Task Run(ProcedureContext context) { if (!CanRun) { throw new InvalidOperationException("Project is already running."); } try { State = ProjectRunnerState.Compiling; _currentSession = await Project.Run(context); } catch (Exception ex) { State = ProjectRunnerState.None; throw ex; } State = ProjectRunnerState.Running; try { var result = await _currentSession.WaitForCompletion(); State = ProjectRunnerState.Completed; } catch (OperationCanceledException) { State = ProjectRunnerState.Aborted; throw; } catch (Exception) { State = ProjectRunnerState.Failed; throw; } } public void Stop() { _currentSession?.Abort(); State = ProjectRunnerState.Aborted; } } }