#if NET20 || NET30 || NET35 || !NET_4_6 using System.Diagnostics.Contracts; namespace System.Threading.Tasks { /// Provides the standard implementation of a task continuation. internal class StandardTaskContinuation : TaskContinuation { /// The unstarted continuation task. internal readonly Task Task; /// The options to use with the continuation task. internal readonly TaskContinuationOptions Options; /// The task scheduler with which to run the continuation task. private readonly TaskScheduler _scheduler; /// Initializes a new continuation. /// The task to be activated. /// The continuation options. /// The scheduler to use for the continuation. internal StandardTaskContinuation(Task task, TaskContinuationOptions options, TaskScheduler scheduler) { Contract.Requires(task != null, "TaskContinuation ctor: task is null"); Contract.Requires(scheduler != null, "TaskContinuation ctor: scheduler is null"); Task = task; Options = options; _scheduler = scheduler; } /// Invokes the continuation for the target completion task. /// The completed task. /// Whether the continuation can be inlined. internal override void Run(Task completedTask, bool canInlineContinuationTask) { if (completedTask == null) { Contract.Assert(false); throw new InvalidOperationException(); } Contract.Assert(completedTask.IsCompleted, "ContinuationTask.Run(): completedTask not completed"); // Check if the completion status of the task works with the desired // activation criteria of the TaskContinuationOptions. var options = Options; var isRightKind = completedTask.Status == TaskStatus.RanToCompletion ? (options & TaskContinuationOptions.NotOnRanToCompletion) == 0 : (completedTask.IsCanceled ? (options & TaskContinuationOptions.NotOnCanceled) == 0 : (options & TaskContinuationOptions.NotOnFaulted) == 0); // If the completion status is allowed, run the continuation. var continuationTask = Task; if (isRightKind) { continuationTask.ExecutingTaskScheduler = _scheduler; // Either run directly or just queue it up for execution, depending // on whether synchronous or asynchronous execution is wanted. if (canInlineContinuationTask && (options & TaskContinuationOptions.ExecuteSynchronously) != 0) { // synchronous execution was requested by the continuation's creator InlineIfPossibleOrElseQueue(continuationTask); } else { try { continuationTask.TryStart(continuationTask.ExecutingTaskScheduler, false); } catch (TaskSchedulerException exception) { // No further action is necessary -- ScheduleAndStart() already transitioned the // task to faulted. But we want to make sure that no exception is thrown from here. GC.KeepAlive(exception); } } } // Otherwise, the final state of this task does not match the desired // continuation activation criteria; cancel it to denote this. else { continuationTask.InternalCancel(false); } } } } #endif