/// <summary>Initializes a new continuation.</summary> /// <param name="task">The task to be activated.</param> /// <param name="options">The continuation options.</param> /// <param name="scheduler">The scheduler to use for the continuation.</param> internal StandardTaskContinuation(Task task, TaskContinuationOptions options, TaskScheduler scheduler) { Debug.Assert(task != null, "TaskContinuation ctor: task is null"); Debug.Assert(scheduler != null, "TaskContinuation ctor: scheduler is null"); m_task = task; m_options = options; m_taskScheduler = scheduler; if (DebuggerSupport.LoggingOn) DebuggerSupport.TraceOperationCreation(CausalityTraceLevel.Required, m_task, "Task.ContinueWith: " + task.m_action, 0); DebuggerSupport.AddToActiveTasks(m_task); }
/// <summary>Invokes the continuation for the target completion task.</summary> /// <param name="completedTask">The completed task.</param> /// <param name="bCanInlineContinuationTask">Whether the continuation can be inlined.</param> internal override void Run(Task completedTask, bool bCanInlineContinuationTask) { Debug.Assert(completedTask != null); Debug.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. TaskContinuationOptions options = m_options; bool isRightKind = completedTask.IsCompletedSuccessfully ? (options & TaskContinuationOptions.NotOnRanToCompletion) == 0 : (completedTask.IsCanceled ? (options & TaskContinuationOptions.NotOnCanceled) == 0 : (options & TaskContinuationOptions.NotOnFaulted) == 0); // If the completion status is allowed, run the continuation. Task continuationTask = m_task; if (isRightKind) { if (!continuationTask.IsCanceled && DebuggerSupport.LoggingOn) { // Log now that we are sure that this continuation is being ran DebuggerSupport.TraceOperationRelation(CausalityTraceLevel.Important, continuationTask, CausalityRelation.AssignDelegate); } continuationTask.m_taskScheduler = m_taskScheduler; // Either run directly or just queue it up for execution, depending // on whether synchronous or asynchronous execution is wanted. if (bCanInlineContinuationTask && // inlining is allowed by the caller (options & TaskContinuationOptions.ExecuteSynchronously) != 0) // synchronous execution was requested by the continuation's creator { InlineIfPossibleOrElseQueue(continuationTask, needsProtection: true); } else { try { continuationTask.ScheduleAndStart(needsProtection: true); } catch (TaskSchedulerException) { // 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. } } } // Otherwise, the final state of this task does not match the desired // continuation activation criteria; cancel it to denote this. else { continuationTask.InternalCancel(false); } }