Inheritance: System.Exception
        /// <summary>
        /// Runs a framework job
        /// </summary>
        /// <param name="workflowMessage">The Queue message</param>
        /// <param name="retryJobTimes">Times to retry the job or steps</param>
        public void RunFrameworkJob(IWorkflowMessage workflowMessage, int retryJobTimes, bool isCheckDepends)
        {
            // For each job, open a new ProcessorJob to keep track of logging
            ProcessorJob currentJob = (ProcessorJob)ProcessorJob.Clone();

            foreach (ProcessorStep workflowStep in currentJob.WorkFlowSteps)
            {
                try
                {
                    int retryStepTimes = 0;
                    workflowStep.RunStatus = FrameworkStepRunStatus.Waiting;
                    if (workflowStep.RunMode == FrameworkStepRunMode.STA)
                        stepExecutor.RunFrameworkStep(workflowMessage, retryStepTimes, workflowStep, currentJob, isCheckDepends);
                    else if (workflowStep.RunMode == FrameworkStepRunMode.MTA)
                        Task.Factory.StartNew(() => stepExecutor.RunFrameworkStep(workflowMessage, retryStepTimes, workflowStep, currentJob, isCheckDepends));
                }
                catch (Exception e)
                {
                    WorkflowException exception = new WorkflowException("Error in framework step " + workflowStep.StepName, e);
                    workflowStep.ExitMessage = e.Message;
                    switch (workflowStep.OnError)
                    {
                        case OnFrameworkStepError.RetryJob:
                            if (workflowStep.WaitBetweenRetriesMilliseconds > 0)
                                Thread.Sleep(workflowStep.WaitBetweenRetriesMilliseconds);
                            retryJobTimes++;
                            Processor.ReportJobError(e, workflowStep, workflowMessage, currentJob);
                            // Try the job again
                            if (retryJobTimes <= workflowStep.RetryTimes)
                                RunFrameworkJob(workflowMessage, retryJobTimes, isCheckDepends);
                            break;
                        case OnFrameworkStepError.Skip:
                            // Skip this step. Doing nothing here will skip it
                            Processor.ReportJobError(e, workflowStep, workflowMessage, currentJob);
                            break;
                        case OnFrameworkStepError.Exit:
                            // Push to to error queue with the error and exit the job
                            Processor.ReportJobError(e, workflowStep, workflowMessage, currentJob);
                            return;
                    }
                }
            }

            // If all steps ran without error report successful job compilation
            Processor.ReportJobComplete(workflowMessage, currentJob);
        }
        /// <summary>
        /// Run a step
        /// </summary>
        /// <param name="currentPipelineInfo"></param>
        /// <param name="workflowStep"></param>
        /// <param name="currentStepNumber"></param>
        /// <returns>The PipelineInfo to be passed to the next step</returns>
        private PipelineInfo RunParalleledPipelinedStep(PipelineInfo currentPipelineInfo)
        {
            if (!currentPipelineInfo.IsInProcess) // This job has been canceled.
                return currentPipelineInfo;

            ProcessorStep workflowStep = currentPipelineInfo.CurrentJob.WorkFlowSteps[currentPipelineInfo.CurrentStepNumber];
            try
            {
                workflowStep.RunStatus = FrameworkStepRunStatus.Waiting;
                if (workflowStep.RunMode == FrameworkStepRunMode.STA)
                    stepExecutor.RunFrameworkStep(currentPipelineInfo.WorkflowMessage, currentPipelineInfo.RetryStepTimes, workflowStep, currentPipelineInfo.CurrentJob, currentPipelineInfo.IsCheckDepends);
                else if (workflowStep.RunMode == FrameworkStepRunMode.MTA)
                    Task.Factory.StartNew(() => stepExecutor.RunFrameworkStep(currentPipelineInfo.WorkflowMessage, currentPipelineInfo.RetryStepTimes, workflowStep, currentPipelineInfo.CurrentJob, currentPipelineInfo.IsCheckDepends));
             
                currentPipelineInfo.CurrentStepNumber++;
                return currentPipelineInfo;
            }
            catch (Exception e)
            {
                WorkflowException exception = new WorkflowException("Error in framework step " + workflowStep.StepName, e);
                workflowStep.ExitMessage = e.Message;
                switch (workflowStep.OnError)
                {
                    case OnFrameworkStepError.RetryJob:
                        if (workflowStep.WaitBetweenRetriesMilliseconds > 0)
                            Thread.Sleep(workflowStep.WaitBetweenRetriesMilliseconds);
                        currentPipelineInfo.RetryJobTimes++;
                        Processor.ReportJobError(e, workflowStep, currentPipelineInfo.WorkflowMessage, currentPipelineInfo.CurrentJob);
                        // Try the job again
                        if (currentPipelineInfo.RetryJobTimes <= workflowStep.RetryTimes)
                            RunFrameworkJob(currentPipelineInfo.WorkflowMessage, currentPipelineInfo.RetryJobTimes, currentPipelineInfo.IsCheckDepends);
                        currentPipelineInfo.IsInProcess = false;
                        return currentPipelineInfo;
                    case OnFrameworkStepError.Skip:
                        // Skip this step. Doing nothing here will skip it
                        Processor.ReportJobError(e, workflowStep, currentPipelineInfo.WorkflowMessage, currentPipelineInfo.CurrentJob);
                        currentPipelineInfo.CurrentStepNumber++;
                        return currentPipelineInfo;
                    case OnFrameworkStepError.Exit:
                        // Push to to error queue with the error and do not continue to the next pipe
                        Processor.ReportJobError(e, workflowStep, currentPipelineInfo.WorkflowMessage, currentPipelineInfo.CurrentJob);
                        currentPipelineInfo.IsInProcess = false;
                        return currentPipelineInfo;
                    default:
                        return currentPipelineInfo;
                }
            }
        }