/// <summary> /// Execute the workflow from the beginning. /// </summary> public WorkflowState Execute(T data) { WorkflowContinuation <T> continuation = new WorkflowContinuation <T>(this); WorkflowState state = InternalContinue(continuation, data); return(state); }
/// <summary> /// Internally, we execute workflow steps until: /// 1. we reach the end of the workflow chain /// 2. we are instructed to abort the workflow /// 3. we are instructed to defer execution until later. /// </summary> protected WorkflowState InternalContinue(WorkflowContinuation <T> wc, T data) { WorkflowState state = WorkflowState.Done; while ((wc.WorkflowStep < items.Count) && !wc.Abort && !wc.Defer && !wc.Done) { try { state = items[wc.WorkflowStep++].Execute(wc, data); switch (state) { case WorkflowState.Abort: wc.Abort = true; wc.Workflow.AbortHandler(data); break; case WorkflowState.Defer: wc.Defer = true; break; case WorkflowState.Done: wc.Done = true; break; } } catch (Exception ex) { // Yes, the user's exception handler could itself through an exception // from which we need to protect ourselves. try { wc.Workflow.ExceptionHandler(data, ex); } catch { /* Now what? */ } // TODO: Should we use a different flag, like "Exception"? Can't be Abort, as this invokes an app-specific handler. state = WorkflowState.Exception; wc.Done = true; } } if (wc.Defer) { // Synchronization, we're done with this loop and the workflow can now continue on another thread. wc.Deferred = true; } // If the loop exits and the last workflow state was continue, then we're actually now done. if (state == WorkflowState.Continue) { state = WorkflowState.Done; } return(state); }
/// <summary> /// Continue a deferred workflow, unless it is aborted. /// </summary> public WorkflowState Continue(WorkflowContinuation <T> wc, T data) { WorkflowState state = WorkflowState.Undefined; // TODO: Throw exception instead? if ((!wc.Abort) && (!wc.Done)) { wc.Defer = false; wc.Deferred = false; state = InternalContinue(wc, data); } return(state); }
/// <summary> /// Execute the workflow item method. /// </summary> public WorkflowState Execute(WorkflowContinuation <T> workflowContinuation, T data) { return(doWork(workflowContinuation, data)); }