/// <summary> /// Executes job's child jobs synchronously. /// </summary> /// <param name="tasksExecuted"> /// Receives the number of tasks executed by this job's child jobs. /// </param> /// <returns> /// The result of the execution of this job's child jobs. /// </returns> private OrchestratedExecutionResult ExecuteChildJobsSynchronous(out int tasksExecuted) { OrchestratedExecutionResult result = OrchestratedExecutionResult.Success; tasksExecuted = 0; if (Job.ChildJobs != null) { Log.Verbose("ScheduledJob ID {0}: Executing synchronous job type {1} child jobs.", JobDetails.JobId, Job.GetType().Name); foreach (IOrchestratedJob job in Job.ChildJobs) { JobOrchestrator jobOrchestrator = new JobOrchestrator(job, JobDetails, Log); OrchestratedExecutionResult jobResult = jobOrchestrator.Execute(out tasksExecuted); if (jobResult == OrchestratedExecutionResult.TerminalError) { result = jobResult; break; } else if (jobResult == OrchestratedExecutionResult.NonTerminalError) { result = jobResult; } } } return(result); }
/// <summary> /// Executes job tasks and child jobs asynchronously. /// </summary> /// <param name="tasksExecuted"> /// Receives the number of tasks executed by this job and all child jobs. /// </param> /// <returns> /// The result of the execution of this job and all child jobs. /// </returns> private OrchestratedExecutionResult ExecuteAsynchronous(out int tasksExecuted) { OrchestratedExecutionResult result = OrchestratedExecutionResult.Success; tasksExecuted = 0; Log.Verbose("ScheduledJob ID {0}: Executing job type {1} tasks and child jobs asynchronously.", JobDetails.JobId, Job.GetType().Name); // Determine how many item will execute while running this job. int itemCount = 0; if (Job.Tasks != null) { itemCount = Job.Tasks.Count; } if (Job.ChildJobs != null) { itemCount += Job.ChildJobs.Count; } // If there are any items to execute, do so asynchronously. if (itemCount > 0) { // Spin up threads to execute the tasks and child jobs. List <Task> executors = new List <Task>(itemCount); ConcurrentDictionary <Guid, Tuple <int, OrchestratedExecutionResult> > itemTaskResults = new ConcurrentDictionary <Guid, Tuple <int, OrchestratedExecutionResult> >(itemCount, itemCount); if (Job.Tasks != null) { IEnumerable <OrchestratedExecutionResult> results = ParallelTaskThrottler.Instance.Run(Job.Tasks); foreach (OrchestratedExecutionResult orchestratedExecutionResult in results) { itemTaskResults[Guid.NewGuid()] = new Tuple <int, OrchestratedExecutionResult>(1, orchestratedExecutionResult); } } if (Job.ChildJobs != null) { foreach (IOrchestratedJob job in Job.ChildJobs) { JobOrchestrator jobOrchestrator = new JobOrchestrator(job, JobDetails, Log); executors.Add(Task.Factory.StartNew(() => { int childTasksExecuted; OrchestratedExecutionResult childResult = jobOrchestrator.Execute(out childTasksExecuted); itemTaskResults[Guid.NewGuid()] = new Tuple <int, OrchestratedExecutionResult>(childTasksExecuted, childResult); })); } } // Wait until all threads have completed their work. Task.WaitAll(executors.ToArray()); // Tally up the completed tasks and get overall result. foreach (Guid key in itemTaskResults.Keys) { Tuple <int, OrchestratedExecutionResult> itemTaskResult = itemTaskResults[key]; tasksExecuted += itemTaskResult.Item1; if (itemTaskResult.Item2 == OrchestratedExecutionResult.TerminalError) { result = OrchestratedExecutionResult.TerminalError; } else if (itemTaskResult.Item2 == OrchestratedExecutionResult.NonTerminalError && result != OrchestratedExecutionResult.TerminalError) { result = OrchestratedExecutionResult.NonTerminalError; } } } return(result); }