#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