future.cs source code in C# .NET

Source code for the .NET framework in C#

                        

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.
                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK