Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Threading / Tasks / future.cs / 1305376 / future.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// Future.cs
//
// [....]
//
// A task that produces a value.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Diagnostics;
using System.Diagnostics.Contracts;
// Disable the "reference to volatile field not treated as volatile" error.
#pragma warning disable 0420
namespace System.Threading.Tasks
{
///
/// Represents an asynchronous operation that produces a result at some time in the future.
///
///
/// The type of the result produced by this .
///
///
///
/// instances may be created in a variety of ways. The most common approach is by
/// using the task's property to retrieve a instance that can be used to create tasks for several
/// purposes. For example, to create a that runs a function, the factory's StartNew
/// method may be used:
///
/// // C#
/// var t = Task<int>.Factory.StartNew(() => GenerateResult());
/// - or -
/// var t = Task.Factory.StartNew(() => GenerateResult());
///
/// ' Visual Basic
/// Dim t = Task<int>.Factory.StartNew(Function() GenerateResult())
/// - or -
/// Dim t = Task.Factory.StartNew(Function() GenerateResult())
///
///
///
/// The class also provides constructors that initialize the task but that do not
/// schedule it for execution. For performance reasons, the StartNew method should be the
/// preferred mechanism for creating and scheduling computational tasks, but for scenarios where creation
/// and scheduling must be separated, the constructors may be used, and the task's
/// Start
/// method may then be used to schedule the task for execution at a later time.
///
///
/// All members of , except for
/// Dispose , are thread-safe
/// and may be used from multiple threads concurrently.
///
///
[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
[DebuggerTypeProxy(typeof(SystemThreadingTasks_FutureDebugView<>))]
[DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}, Result = {DebuggerDisplayResultDescription}")]
public class Task : Task
{
private object m_valueSelector; // The function which produces a value.
private TResult m_result; // The value itself, if set.
internal bool m_resultWasSet; // Whether the value has been set (needed for structs).
private object m_futureState;
private static TaskFactory s_Factory = new TaskFactory();
// Construct a promise-style task with state and options. Only used internally, for
// initializing TaskCompletionSource.m_task.
internal Task(object state, CancellationToken cancellationToken, TaskCreationOptions options, InternalTaskOptions internalOptions)
: base(null, cancellationToken, options, internalOptions, true)
{
m_valueSelector = null;
m_futureState = state;
}
// Construct a pre-completed Task
internal Task(bool canceled, TResult result, TaskCreationOptions creationOptions)
: base(canceled, creationOptions)
{
if (!canceled)
{
m_result = result;
m_resultWasSet = true;
}
}
///
/// Initializes a new with the specified function.
///
///
/// The delegate that represents the code to execute in the task. When the function has completed,
/// the task's property will be set to return the result value of the function.
///
///
/// The argument is null.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func function)
: this(function, Task.InternalCurrent, CancellationToken.None,
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
PossiblyCaptureContext(ref stackMark);
}
///
/// Initializes a new with the specified function.
///
///
/// The delegate that represents the code to execute in the task. When the function has completed,
/// the task's property will be set to return the result value of the function.
///
/// The to be assigned to this task.
///
/// The argument is null.
///
/// The provided CancellationToken
/// has already been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func function, CancellationToken cancellationToken)
: this(function, Task.InternalCurrent, cancellationToken,
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
PossiblyCaptureContext(ref stackMark);
}
///
/// Initializes a new with the specified function and creation options.
///
///
/// The delegate that represents the code to execute in the task. When the function has completed,
/// the task's property will be set to return the result value of the function.
///
///
/// The TaskCreationOptions used to
/// customize the task's behavior.
///
///
/// The argument is null.
///
///
/// The argument specifies an invalid value for .
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func function, TaskCreationOptions creationOptions)
: this(function, Task.InternalCurrent, CancellationToken.None, creationOptions, InternalTaskOptions.None, null)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
PossiblyCaptureContext(ref stackMark);
}
///
/// Initializes a new with the specified function and creation options.
///
///
/// The delegate that represents the code to execute in the task. When the function has completed,
/// the task's property will be set to return the result value of the function.
///
/// The that will be assigned to the new task.
///
/// The TaskCreationOptions used to
/// customize the task's behavior.
///
///
/// The argument is null.
///
///
/// The argument specifies an invalid value for .
///
/// The provided CancellationToken
/// has already been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func function, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
: this(function, Task.InternalCurrent, cancellationToken, creationOptions, InternalTaskOptions.None, null)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
PossiblyCaptureContext(ref stackMark);
}
///
/// Initializes a new with the specified function and state.
///
///
/// The delegate that represents the code to execute in the task. When the function has completed,
/// the task's property will be set to return the result value of the function.
///
/// An object representing data to be used by the action.
///
/// The argument is null.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func function, object state)
: this(function, state, Task.InternalCurrent, CancellationToken.None,
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
PossiblyCaptureContext(ref stackMark);
}
///
/// Initializes a new with the specified action, state, and options.
///
///
/// The delegate that represents the code to execute in the task. When the function has completed,
/// the task's property will be set to return the result value of the function.
///
/// An object representing data to be used by the function.
/// The to be assigned to the new task.
///
/// The argument is null.
///
/// The provided CancellationToken
/// has already been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func function, object state, CancellationToken cancellationToken)
: this(function, state, Task.InternalCurrent, cancellationToken,
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
PossiblyCaptureContext(ref stackMark);
}
///
/// Initializes a new with the specified action, state, and options.
///
///
/// The delegate that represents the code to execute in the task. When the function has completed,
/// the task's property will be set to return the result value of the function.
///
/// An object representing data to be used by the function.
///
/// The TaskCreationOptions used to
/// customize the task's behavior.
///
///
/// The argument is null.
///
///
/// The argument specifies an invalid value for .
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func function, object state, TaskCreationOptions creationOptions)
: this(function, state, Task.InternalCurrent, CancellationToken.None,
creationOptions, InternalTaskOptions.None, null)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
PossiblyCaptureContext(ref stackMark);
}
///
/// Initializes a new with the specified action, state, and options.
///
///
/// The delegate that represents the code to execute in the task. When the function has completed,
/// the task's property will be set to return the result value of the function.
///
/// An object representing data to be used by the function.
/// The to be assigned to the new task.
///
/// The TaskCreationOptions used to
/// customize the task's behavior.
///
///
/// The argument is null.
///
///
/// The argument specifies an invalid value for .
///
/// The provided CancellationToken
/// has already been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func function, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
: this(function, state, Task.InternalCurrent, cancellationToken,
creationOptions, InternalTaskOptions.None, null)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
PossiblyCaptureContext(ref stackMark);
}
// For Task.ContinueWith() and Future.ContinueWith()
internal Task(
Func valueSelector, Task parent, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler,
ref StackCrawlMark stackMark) :
this(valueSelector, parent, cancellationToken,
creationOptions, internalOptions, scheduler)
{
PossiblyCaptureContext(ref stackMark);
}
///
/// Creates a new future object.
///
/// The parent task for this future.
/// A function that yields the future value.
/// The task scheduler which will be used to execute the future.
/// The CancellationToken for the task.
/// Options to control the future's behavior.
/// Internal options to control the future's behavior.
/// The argument specifies
/// a SelfReplicating , which is illegal."/>.
internal Task(Func valueSelector, Task parent, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
base((valueSelector != null ? InvokeFuture : (Action)null), null, parent, cancellationToken, creationOptions, internalOptions, scheduler)
{
if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
{
throw new ArgumentOutOfRangeException("creationOptions", Environment.GetResourceString("TaskT_ctor_SelfReplicating"));
}
m_valueSelector = valueSelector;
m_stateObject = this;
}
// For Task.ContinueWith() and Future.ContinueWith()
internal Task(
Func valueSelector, object state, Task parent, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark) :
this(valueSelector, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
{
PossiblyCaptureContext(ref stackMark);
}
///
/// Creates a new future object.
///
/// The parent task for this future.
/// An object containing data to be used by the action; may be null.
/// A function that yields the future value.
/// The CancellationToken for the task.
/// The task scheduler which will be used to execute the future.
/// Options to control the future's behavior.
/// Internal options to control the future's behavior.
/// The argument specifies
/// a SelfReplicating , which is illegal."/>.
internal Task(Func valueSelector, object state, Task parent, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
base((valueSelector != null ? InvokeFuture : (Action)null), null, parent, cancellationToken, creationOptions, internalOptions, scheduler)
{
if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
{
throw new ArgumentOutOfRangeException("creationOptions", Environment.GetResourceString("TaskT_ctor_SelfReplicating"));
}
m_valueSelector = valueSelector;
m_stateObject = this;
m_futureState = state; // necessary to differentiate state from "this"
}
// Internal method used by TaskFactory.StartNew() methods
internal static Task StartNew(Task parent, Func function, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark)
{
if (function == null)
{
throw new ArgumentNullException("function");
}
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
{
// @
throw new ArgumentOutOfRangeException("creationOptions", Environment.GetResourceString("TaskT_ctor_SelfReplicating"));
}
// Create and schedule the future.
Task f = new Task(function, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler, ref stackMark);
f.ScheduleAndStart(false);
return f;
}
// Internal method used by TaskFactory.StartNew() methods
internal static Task StartNew(Task parent, Func function, object state, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark)
{
if (function == null)
{
throw new ArgumentNullException("function");
}
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
{
throw new ArgumentOutOfRangeException("creationOptions", Environment.GetResourceString("TaskT_ctor_SelfReplicating"));
}
// Create and schedule the future.
Task f = new Task(function, state, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler, ref stackMark);
f.ScheduleAndStart(false);
return f;
}
// Debugger support
private string DebuggerDisplayResultDescription
{
get { return m_resultWasSet ? "" + m_result : Environment.GetResourceString("TaskT_DebuggerNoResult"); }
}
// Debugger support
private string DebuggerDisplayMethodDescription
{
get
{
Delegate d = (Delegate)m_valueSelector;
return d != null ? d.Method.ToString() : "{null}";
}
}
// internal helper function breaks out logic used by TaskCompletionSource
internal bool TrySetResult(TResult result)
{
ThrowIfDisposed();
Contract.Assert(m_valueSelector == null, "Task.TrySetResult(): non-null m_valueSelector");
// "Reserve" the completion for this task, while making sure that: (1) No prior reservation
// has been made, (2) The result has not already been set, (3) An exception has not previously
// been recorded, and (4) Cancellation has not been requested.
//
// If the reservation is successful, then set the result and finish completion processing.
if (AtomicStateUpdate(TASK_STATE_COMPLETION_RESERVED,
TASK_STATE_COMPLETION_RESERVED | TASK_STATE_RAN_TO_COMPLETION | TASK_STATE_FAULTED | TASK_STATE_CANCELED))
{
m_result = result;
m_resultWasSet = true;
// Signal completion, for waiting tasks
Finish(false);
return true;
}
return false;
}
///
/// Gets the result value of this .
///
///
/// The get accessor for this property ensures that the asynchronous operation is complete before
/// returning. Once the result of the computation is available, it is stored and will be returned
/// immediately on later calls to .
///
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public TResult Result
{
get
{
// If the result has not been calculated yet, wait for it.
if (!IsCompleted)
{
// We call NOCTD for two reasons:
// 1. If the task runs on another thread, then we definitely need to notify that thread-slipping is required.
// 2. If the task runs inline but takes some time to complete, it will suffer ThreadAbort with possible state corruption.
// - it is best to prevent this unless the user explicitly asks to view the value with thread-slipping enabled.
#if !PFX_LEGACY_3_5
Debugger.NotifyOfCrossThreadDependency();
#endif
Wait();
}
// Throw an exception if appropriate.
ThrowIfExceptional(!m_resultWasSet);
// We shouldn't be here if the result has not been set.
Contract.Assert(m_resultWasSet, "Task.Result getter: Expected result to have been set.");
return m_result;
}
internal set
{
if (m_valueSelector != null)
{
throw new InvalidOperationException(Environment.GetResourceString("TaskT_SetResult_HasAnInitializer"));
}
if (!TrySetResult(value))
{
throw new InvalidOperationException(Environment.GetResourceString("TaskT_TransitionToFinal_AlreadyCompleted"));
}
}
}
// Allow multiple exceptions to be assigned to a promise-style task.
// This is useful when a TaskCompletionSource stands in as a proxy
// for a "real" task (as we do in Unwrap(), ContinueWhenAny() and ContinueWhenAll())
// and the "real" task ends up with multiple exceptions, which is possible when
// a task has children.
//
// Called from TaskCompletionSource.SetException(IEnumerable).
internal bool TrySetException(object exceptionObject)
{
ThrowIfDisposed();
Contract.Assert(m_valueSelector == null, "Task.TrySetException(): non-null m_valueSelector");
// TCS.{Try}SetException() should have checked for this
Contract.Assert(exceptionObject != null, "Expected non-null exceptionObject argument");
// Only accept these types.
Contract.Assert((exceptionObject is Exception) || (exceptionObject is IEnumerable),
"Expected exceptionObject to be either Exception or IEnumerable");
bool returnValue = false;
// "Reserve" the completion for this task, while making sure that: (1) No prior reservation
// has been made, (2) The result has not already been set, (3) An exception has not previously
// been recorded, and (4) Cancellation has not been requested.
//
// If the reservation is successful, then add the exception(s) and finish completion processing.
//
// The lazy initialization may not be strictly necessary, but I'd like to keep it here
// anyway. Some downstream logic may depend upon an inflated m_contingentProperties.
LazyInitializer.EnsureInitialized(ref m_contingentProperties, Task.s_contingentPropertyCreator);
if (AtomicStateUpdate(TASK_STATE_COMPLETION_RESERVED,
TASK_STATE_COMPLETION_RESERVED | TASK_STATE_RAN_TO_COMPLETION | TASK_STATE_FAULTED | TASK_STATE_CANCELED))
{
AddException(exceptionObject); // handles singleton exception or exception collection
Finish(false);
returnValue = true;
}
return returnValue;
}
///
/// Provides access to factory methods for creating instances.
///
///
/// The factory returned from is a default instance
/// of , as would result from using
/// the default constructor on the factory type.
///
public new static TaskFactory Factory { get { return s_Factory; } }
// Allow Task.AsyncState, inherited from Task, to function correctly.
internal override object InternalAsyncState
{
get { return m_futureState; }
}
///
/// Evaluates the value selector of the Task which is passed in as an object and stores the result.
///
private static void InvokeFuture(object futureAsObj)
{
Task f = ((Task)futureAsObj);
Contract.Assert(f.m_valueSelector != null);
// f.m_value can be a Func or a Func. Figure out which one it is and do the right thing.
Func func = f.m_valueSelector as Func;
try
{
if (func != null)
f.m_result = func();
else
f.m_result = ((Func)f.m_valueSelector)(f.m_futureState);
f.m_resultWasSet = true;
}
finally
{
f.m_valueSelector = null; // bound memory usage in long continuation chains
}
}
///
/// Creates a continuation that executes when the target completes.
///
///
/// An action to run when the completes. When run, the delegate will be
/// passed the completed task as an argument.
///
/// A new continuation .
///
/// The returned will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
///
///
/// The argument is null.
///
///
/// The has been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action> continuationAction)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return ContinueWith(continuationAction, TaskScheduler.Current, CancellationToken.None, TaskContinuationOptions.None, ref stackMark);
}
///
/// Creates a continuation that executes when the target completes.
///
///
/// An action to run when the completes. When run, the delegate will be
/// passed the completed task as an argument.
///
/// The that will be assigned to the new continuation task.
/// A new continuation .
///
/// The returned will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
///
///
/// The argument is null.
///
///
/// The has been disposed.
///
/// The provided CancellationToken
/// has already been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action> continuationAction, CancellationToken cancellationToken)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return ContinueWith(continuationAction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
}
///
/// Creates a continuation that executes when the target completes.
///
///
/// An action to run when the completes. When run, the delegate will be
/// passed the completed task as an argument.
///
///
/// The to associate with the continuation task and to use for its execution.
///
/// A new continuation .
///
/// The returned will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
///
///
/// The argument is null.
///
///
/// The argument is null.
///
///
/// The has been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action> continuationAction, TaskScheduler scheduler)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return ContinueWith(continuationAction, scheduler, CancellationToken.None, TaskContinuationOptions.None, ref stackMark);
}
///
/// Creates a continuation that executes when the target completes.
///
///
/// An action to run when the completes. When run, the delegate will be
/// passed the completed task as an argument.
///
///
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as OnlyOnCanceled , as
/// well as execution options, such as ExecuteSynchronously .
///
/// A new continuation .
///
/// The returned will not be scheduled for execution until the current task has
/// completed. If the continuation criteria specified through the parameter are not met, the continuation task will be canceled
/// instead of scheduled.
///
///
/// The argument is null.
///
///
/// The argument specifies an invalid value for TaskContinuationOptions .
///
///
/// The has been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action> continuationAction, TaskContinuationOptions continuationOptions)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return ContinueWith(continuationAction, TaskScheduler.Current, CancellationToken.None, continuationOptions, ref stackMark);
}
///
/// Creates a continuation that executes when the target completes.
///
///
/// An action to run when the completes. When run, the delegate will be
/// passed the completed task as an argument.
///
/// The that will be assigned to the new continuation task.
///
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as OnlyOnCanceled , as
/// well as execution options, such as ExecuteSynchronously .
///
///
/// The to associate with the continuation task and to use for its
/// execution.
///
/// A new continuation .
///
/// The returned will not be scheduled for execution until the current task has
/// completed. If the criteria specified through the parameter
/// are not met, the continuation task will be canceled instead of scheduled.
///
///
/// The argument is null.
///
///
/// The argument specifies an invalid value for TaskContinuationOptions .
///
///
/// The argument is null.
///
///
/// The has been disposed.
///
/// The provided CancellationToken
/// has already been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action> continuationAction, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return ContinueWith(continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
}
// Same as the above overload, only with a stack mark.
internal Task ContinueWith(Action> continuationAction, TaskScheduler scheduler, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
{
ThrowIfDisposed();
if (continuationAction == null)
{
throw new ArgumentNullException("continuationAction");
}
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
TaskCreationOptions creationOptions;
InternalTaskOptions internalOptions;
CreationOptionsFromContinuationOptions(
continuationOptions,
out creationOptions,
out internalOptions);
Task thisFuture = this;
Task continuationTask = new Task(
delegate(object obj) { continuationAction(thisFuture); },
null,
Task.InternalCurrent,
cancellationToken,
creationOptions,
internalOptions,
null, // leave scheduler null until TaskContinuation.Run() is called
ref stackMark
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
ContinueWithCore(continuationTask, scheduler, continuationOptions);
return continuationTask;
}
///
/// Creates a continuation that executes when the target completes.
///
///
/// The type of the result produced by the continuation.
///
///
/// A function to run when the completes. When run, the delegate will be
/// passed the completed task as an argument.
///
/// A new continuation .
///
/// The returned will not be scheduled for execution until the current
/// task has completed, whether it completes due to running to completion successfully, faulting due
/// to an unhandled exception, or exiting out early due to being canceled.
///
///
/// The argument is null.
///
///
/// The has been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Func, TNewResult> continuationFunction)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return ContinueWith(continuationFunction, TaskScheduler.Current, CancellationToken.None, TaskContinuationOptions.None, ref stackMark);
}
///
/// Creates a continuation that executes when the target completes.
///
///
/// The type of the result produced by the continuation.
///
///
/// A function to run when the completes. When run, the delegate will be
/// passed the completed task as an argument.
///
/// The that will be assigned to the new task.
/// A new continuation .
///
/// The returned will not be scheduled for execution until the current
/// task has completed, whether it completes due to running to completion successfully, faulting due
/// to an unhandled exception, or exiting out early due to being canceled.
///
///
/// The argument is null.
///
///
/// The has been disposed.
///
/// The provided CancellationToken
/// has already been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Func, TNewResult> continuationFunction, CancellationToken cancellationToken)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return ContinueWith(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
}
///
/// Creates a continuation that executes when the target completes.
///
///
/// The type of the result produced by the continuation.
///
///
/// A function to run when the completes. When run, the delegate will be
/// passed the completed task as an argument.
///
///
/// The to associate with the continuation task and to use for its execution.
///
/// A new continuation .
///
/// The returned will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
///
///
/// The argument is null.
///
///
/// The argument is null.
///
///
/// The has been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Func, TNewResult> continuationFunction, TaskScheduler scheduler)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return ContinueWith(continuationFunction, scheduler, CancellationToken.None, TaskContinuationOptions.None, ref stackMark);
}
///
/// Creates a continuation that executes when the target completes.
///
///
/// The type of the result produced by the continuation.
///
///
/// A function to run when the completes. When run, the delegate will be
/// passed the completed task as an argument.
///
///
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as OnlyOnCanceled , as
/// well as execution options, such as ExecuteSynchronously .
///
/// A new continuation .
///
///
/// The returned will not be scheduled for execution until the current
/// task has completed, whether it completes due to running to completion successfully, faulting due
/// to an unhandled exception, or exiting out early due to being canceled.
///
///
/// The , when executed, should return a . This task's completion state will be transferred to the task returned
/// from the ContinueWith call.
///
///
///
/// The argument is null.
///
///
/// The argument specifies an invalid value for TaskContinuationOptions .
///
///
/// The has been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Func, TNewResult> continuationFunction, TaskContinuationOptions continuationOptions)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return ContinueWith(continuationFunction, TaskScheduler.Current, CancellationToken.None, continuationOptions, ref stackMark);
}
///
/// Creates a continuation that executes when the target completes.
///
///
/// The type of the result produced by the continuation.
///
///
/// A function to run when the completes. When run, the delegate will be passed as
/// an argument this completed task.
///
/// The that will be assigned to the new task.
///
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as OnlyOnCanceled , as
/// well as execution options, such as ExecuteSynchronously .
///
///
/// The to associate with the continuation task and to use for its
/// execution.
///
/// A new continuation .
///
///
/// The returned will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
///
///
/// The , when executed, should return a .
/// This task's completion state will be transferred to the task returned from the
/// ContinueWith call.
///
///
///
/// The argument is null.
///
///
/// The argument specifies an invalid value for TaskContinuationOptions .
///
///
/// The argument is null.
///
///
/// The has been disposed.
///
/// The provided CancellationToken
/// has already been disposed.
///
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Func, TNewResult> continuationFunction, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return ContinueWith(continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
}
// Same as the above overload, just with a stack mark.
internal Task ContinueWith(Func, TNewResult> continuationFunction, TaskScheduler scheduler,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
{
ThrowIfDisposed();
if (continuationFunction == null)
{
throw new ArgumentNullException("continuationFunction");
}
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
TaskCreationOptions creationOptions;
InternalTaskOptions internalOptions;
CreationOptionsFromContinuationOptions(
continuationOptions,
out creationOptions,
out internalOptions);
Task thisFuture = this;
Task continuationFuture = new Task(
delegate() { return continuationFunction(thisFuture); },
Task.InternalCurrent,
cancellationToken,
creationOptions,
internalOptions,
null, // leave scheduler null until TaskContinuation.Run() is called.
ref stackMark
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
ContinueWithCore(continuationFuture, scheduler, continuationOptions);
return continuationFuture;
}
}
// Proxy class for better debugging experience
internal class SystemThreadingTasks_FutureDebugView
{
private Task m_task;
public SystemThreadingTasks_FutureDebugView(Task task)
{
m_task = task;
}
public TResult Result { get { return m_task.Status == TaskStatus.RanToCompletion ? m_task.Result : default(TResult); } }
public object AsyncState { get { return m_task.AsyncState; } }
public TaskCreationOptions CreationOptions { get { return m_task.CreationOptions; } }
public Exception Exception { get { return m_task.Exception; } }
public int Id { get { return m_task.Id; } }
public bool CancellationPending { get { return (m_task.Status == TaskStatus.WaitingToRun) && m_task.CancellationToken.IsCancellationRequested; } }
public TaskStatus Status { get { return m_task.Status; } }
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.