public virtual T Then <T>(T nextTask, TaskRunOptions runOptions = TaskRunOptions.OnSuccess, bool taskIsTopOfChain = false) where T : ITask { Guard.ArgumentNotNull(nextTask, nameof(nextTask)); var nextTaskBase = ((TaskBase)(object)nextTask); // find the task at the top of the chain if (!taskIsTopOfChain) { nextTaskBase = nextTaskBase.GetTopMostTask() ?? nextTaskBase; } // make the next task dependent on this one so it can get values from us nextTaskBase.SetDependsOn(this); var nextTaskFinallyHandler = nextTaskBase.finallyHandler; if (runOptions == TaskRunOptions.OnSuccess) { this.continuationOnSuccess = nextTaskBase; // if there are fault handlers in the chain we're appending, propagate them // up this chain as well if (nextTaskBase.continuationOnFailure != null) { SetFaultHandler(nextTaskBase.continuationOnFailure); } else if (nextTaskBase.continuationOnAlways != null) { SetFaultHandler(nextTaskBase.continuationOnAlways); } if (nextTaskBase.catchHandler != null) { Catch(nextTaskBase.catchHandler); } if (nextTaskFinallyHandler != null) { Finally(nextTaskFinallyHandler); } } else if (runOptions == TaskRunOptions.OnFailure) { this.continuationOnFailure = nextTaskBase; DependsOn?.Then(nextTaskBase, TaskRunOptions.OnFailure, true); } else { this.continuationOnAlways = nextTaskBase; DependsOn?.SetFaultHandler(nextTaskBase); } // if the current task has a fault handler, attach it to the chain we're appending if (finallyHandler != null) { TaskBase endOfChainTask = (TaskBase)nextTaskBase.GetEndOfChain(); while (endOfChainTask != this && endOfChainTask != null) { endOfChainTask.finallyHandler += finallyHandler; endOfChainTask = endOfChainTask.DependsOn; } } return(nextTask); }