Task.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Threading / Tasks / Task.cs / 1305376 / Task.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// 
// Task.cs 
//
// [....] 
//
// A schedulable unit of work.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices; 
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Threading; 
using System.Diagnostics;
using System.Diagnostics.Contracts; 
using System.Diagnostics.Eventing; 
using Microsoft.Win32;
 
// Disable the "reference to volatile field not treated as volatile" error.
#pragma warning disable 0420

namespace System.Threading.Tasks 
{
    ///  
    /// Represents the current stage in the lifecycle of a . 
    /// 
    public enum TaskStatus 
    {
        /// 
        /// The task has been initialized but has not yet been scheduled.
        ///  
        Created,
        ///  
        /// The task is waiting to be activated and scheduled internally by the .NET Framework infrastructure. 
        /// 
        WaitingForActivation, 
        /// 
        /// The task has been scheduled for execution but has not yet begun executing.
        /// 
        WaitingToRun, 
        /// 
        /// The task is running but has not yet completed. 
        ///  
        Running,
        // ///  
        // /// The task is currently blocked in a wait state.
        // /// 
        // Blocked,
        ///  
        /// The task has finished executing and is implicitly waiting for
        /// attached child tasks to complete. 
        ///  
        WaitingForChildrenToComplete,
        ///  
        /// The task completed execution successfully.
        /// 
        RanToCompletion,
        ///  
        /// The task acknowledged cancellation by throwing an OperationCanceledException with its own CancellationToken
        /// while the token was in signaled state, or the task's CancellationToken was already signaled before the 
        /// task started executing. 
        /// 
        Canceled, 
        /// 
        /// The task completed due to an unhandled exception.
        /// 
        Faulted 
    }
 
 
    /// 
    /// Represents an asynchronous operation. 
    /// 
    /// 
    /// 
    ///  instances may be created in a variety of ways. The most common approach is by 
    /// using the Task type's  property to retrieve a  instance that can be used to create tasks for several 
    /// purposes. For example, to create a  that runs an action, the factory's StartNew 
    /// method may be used:
    ///  
    /// // C#
    /// var t = Task.Factory.StartNew(() => DoAction());
    ///
    /// ' Visual Basic 
    /// Dim t = Task.Factory.StartNew(Function() DoAction())
    ///  
    ///  
    /// 
    /// The  class also provides constructors that initialize the Task but that do not 
    /// schedule it for execution. For performance reasons, TaskFactory's 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 
    /// method may then be used to schedule the task for execution at a later time. 
    /// 
    ///  
    /// All members of , except for , are thread-safe 
    /// and may be used from multiple threads concurrently.
    ///  
    /// 
    /// For operations that return values, the  class
    /// should be used.
    ///  
    /// 
    /// For developers implementing custom debuggers, several internal and private members of Task may be 
    /// useful (these may change from release to release). The Int32 m_taskId field serves as the backing 
    /// store for the  property, however accessing this field directly from a debugger may be
    /// more efficient than accessing the same value through the property's getter method (the 
    /// s_taskIdCounter Int32 counter is used to retrieve the next available ID for a Task). Similarly, the
    /// Int32 m_stateFlags field stores information about the current lifecycle stage of the Task,
    /// information also accessible through the  property. The m_action System.Object
    /// field stores a reference to the Task's delegate, and the m_stateObject System.Object field stores the 
    /// async state passed to the Task by the developer. Finally, for debuggers that parse stack frames, the
    /// InternalWait method serves a potential marker for when a Task is entering a wait operation. 
    ///  
    /// 
    [HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)] 
    [DebuggerTypeProxy(typeof(SystemThreadingTasks_TaskDebugView))]
    [DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}")]
    public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable
    { 

        // Accessing ThreadStatic variables on classes with class constructors is much slower than if the class 
        // has no class constructor.  So we declasre s_currentTask inside a nested class with no constructor. 
        // Do not put any static variables with explicit initialization in this class, as it will regress performance.
        private static class ThreadLocals 
        {
            [ThreadStatic]
            internal static Task s_currentTask;  // The currently executing task.
 
            [ThreadStatic]
            internal static StackGuard s_stackGuard;  // The stack guard object for this thread 
        } 

        internal static int s_taskIdCounter; //static counter used to generate unique task IDs 
        private static TaskFactory s_factory = new TaskFactory();

        private int m_taskId; // this task's unique ID. initialized only if it is ever requested
 
        internal object m_action;    // The body of the task.  Might be Action, Action or Action.
        // If m_action is set to null it will indicate that we operate in the 
        // "externally triggered completion" mode, which is exclusively meant 
        // for the signalling Task (aka. promise). In this mode,
        // we don't call InnerInvoke() in response to a Wait(), but simply wait on 
        // the completion event which will be set when the Future class calls Finish().
        // But the event would now be signalled if Cancel() is called

 
        internal object m_stateObject; // A state object that can be optionally supplied, passed to action.
        internal TaskScheduler m_taskScheduler; // The task scheduler this task runs under. @ 
 
        internal readonly Task m_parent; // A task's parent, or null if parent-less.
        internal ExecutionContext m_capturedContext; // The context to run the task within, if any. 

        internal volatile int m_stateFlags;

        // State constants for m_stateFlags; 
        // The bits of m_stateFlags are allocated as follows:
        //   0x40000000 - TaskBase state flag 
        //   0x3FFF0000 - Task state flags 
        //   0x0000FF00 - internal TaskCreationOptions flags
        //   0x000000FF - publicly exposed TaskCreationOptions flags 
        //
        // See TaskCreationOptions for bit values associated with TaskCreationOptions
        //
        private const int OptionsMask = 0xFFFF; // signifies the Options portion of m_stateFlags 
        internal const int TASK_STATE_STARTED = 0x10000;
        internal const int TASK_STATE_DELEGATE_INVOKED = 0x20000; 
        internal const int TASK_STATE_DISPOSED = 0x40000; 
        internal const int TASK_STATE_EXCEPTIONOBSERVEDBYPARENT = 0x80000;
        internal const int TASK_STATE_CANCELLATIONACKNOWLEDGED = 0x100000; 
        internal const int TASK_STATE_FAULTED = 0x200000;
        internal const int TASK_STATE_CANCELED = 0x400000;
        internal const int TASK_STATE_WAITING_ON_CHILDREN = 0x800000;
        internal const int TASK_STATE_RAN_TO_COMPLETION = 0x1000000; 
        internal const int TASK_STATE_WAITINGFORACTIVATION = 0x2000000;
        internal const int TASK_STATE_COMPLETION_RESERVED = 0x4000000; 
        internal const int TASK_STATE_THREAD_WAS_ABORTED = 0x8000000; 

        // Values for ContingentProperties.m_internalCancellationRequested. 
        internal static int CANCELLATION_REQUESTED = 0x1;

        private volatile ManualResetEventSlim m_completionEvent; // Lazily created if waiting is required.
 
        // We moved a number of Task properties into this class.  The idea is that in most cases, these properties never
        // need to be accessed during the life cycle of a Task, so we don't want to instantiate them every time.  Once 
        // one of these properties needs to be written, we will instantiate a ContingentProperties object and set 
        // the appropriate property.
        internal class ContingentProperties 
        {
            public volatile int m_internalCancellationRequested; // We keep canceled in its own field because threads legally ---- to set it.

            internal volatile int m_completionCountdown = 1; // # of active children + 1 (for this task itself). 
            // Used for ensuring all children are done before this task can complete
            // The extra count helps prevent the ---- for executing the final state transition 
            // (i.e. whether the last child or this task itself should call FinishStageTwo()) 

            public volatile TaskExceptionHolder m_exceptionsHolder; // Tracks exceptions, if any have occurred 

            public volatile List m_exceptionalChildren;       // A list of child tasks that threw an exception (TCEs don't count),
            // but haven't yet been waited on by the parent, lazily initialized.
 
            public volatile List m_continuations; // A list of tasks or actions to be started upon completion, lazily initialized.
 
            public CancellationToken m_cancellationToken; 
            public Shared m_cancellationRegistration;
        } 

        // This field will only be instantiated to some non-null value if any ContingentProperties need to be set.
        internal volatile ContingentProperties m_contingentProperties;
 
        /// 
        /// A type initializer that runs with the appropriate permissions. 
        ///  
        [SecuritySafeCritical]
        static Task() 
        {
            s_ecCallback = new ContextCallback(ExecutionContextCallback);
        }
 
        // Special internal constructor to create an already-completed task.
        // if canceled==true, create a Canceled task, or else create a RanToCompletion task. 
        internal Task(bool canceled, TaskCreationOptions creationOptions) 
        {
            int optionFlags = (int)creationOptions; 
            if (canceled) m_stateFlags = TASK_STATE_CANCELED | TASK_STATE_CANCELLATIONACKNOWLEDGED | optionFlags;
            else m_stateFlags = TASK_STATE_RAN_TO_COMPLETION | optionFlags;
        }
 
        // Special internal constructor to create an already-Faulted task.
        // Break this out when we need it. 
        // 
        //internal Task(Exception exception, bool attached)
        //{ 
        //    Task m_parent = attached ? Task.InternalCurrent : null;
        //
        //    if(m_parent != null) m_parent.AddNewChild();
        // 
        //    m_contingentProperties = new ContingentProperties();
        //    m_contingentProperties.m_exceptionsHolder = new TaskExceptionHolder(this); 
        //    m_contingentProperties.m_exceptionsHolder.Add(exception); 
        //    m_stateFlags = TASK_STATE_FAULTED;
        // 
        //    if (m_parent != null) m_parent.ProcessChildCompletion(this);
        //}

 

        // Special constructor for use with promise-style tasks. 
        // Added promiseStyle parameter as an aid to the compiler to distinguish between (state,TCO) and 
        // (action,TCO).  It should always be true.
        internal Task(object state, CancellationToken cancelationToken, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, bool promiseStyle) 
        {
            Contract.Assert(promiseStyle, "Promise CTOR: promiseStyle was false");

            // Check the creationOptions. We only allow the attached/detached option to be specified for promise tasks. 
            if ((creationOptions & ~(TaskCreationOptions.AttachedToParent)) != 0)
            { 
                throw new ArgumentOutOfRangeException("creationOptions"); 
            }
 
            if ((internalOptions & ~(InternalTaskOptions.PromiseTask)) != 0)
            {
                throw new ArgumentOutOfRangeException("internalOptions", Environment.GetResourceString("Task_PromiseCtor_IllegalInternalOptions"));
            } 

            // m_parent is readonly, and so must be set in the constructor. 
            // Only set a parent if AttachedToParent is specified. 
            if ((creationOptions & TaskCreationOptions.AttachedToParent) != 0)
                m_parent = Task.InternalCurrent; 

            TaskConstructorCore(null, state, cancelationToken, creationOptions, internalOptions, TaskScheduler.Current);
        }
 
        /// 
        /// Initializes a new  with the specified action. 
        ///  
        /// The delegate that represents the code to execute in the Task.
        /// The  argument is null. 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
        public Task(Action action)
            : this((object)action, null, Task.InternalCurrent, CancellationToken.None, TaskCreationOptions.None, InternalTaskOptions.None, null)
        { 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PossiblyCaptureContext(ref stackMark); 
        } 

        ///  
        /// Initializes a new  with the specified action and CancellationToken.
        /// 
        /// The delegate that represents the code to execute in the Task.
        /// The CancellationToken 
        /// that will 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(Action action, CancellationToken cancellationToken)
            : this((object)action, null, Task.InternalCurrent, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
        { 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PossiblyCaptureContext(ref stackMark); 
        } 

        ///  
        /// Initializes a new  with the specified action and creation options.
        /// 
        /// The delegate that represents the code to execute in the task.
        ///  
        /// 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(Action action, TaskCreationOptions creationOptions) 
            : this((object)action, null, Task.InternalCurrent, CancellationToken.None, creationOptions, InternalTaskOptions.None, null)
        { 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PossiblyCaptureContext(ref stackMark);
        }
 
        /// 
        /// Initializes a new  with the specified action and creation options. 
        ///  
        /// The delegate that represents the code to execute in the task.
        /// 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(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions) 
            : this((object)action, null, Task.InternalCurrent, cancellationToken, creationOptions, InternalTaskOptions.None, null)
        { 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PossiblyCaptureContext(ref stackMark);
        }
 

        ///  
        /// Initializes a new  with the specified action and state. 
        /// 
        /// The delegate that represents the code to execute in the task. 
        /// 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(Action action, object state) 
            : this((object)action, 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, snd options.
        ///  
        /// The delegate that represents the code to execute in the task. 
        /// An object representing data to be used by the action.
        /// The  that will 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(Action action, object state, CancellationToken cancellationToken)
            : this((object)action, state, Task.InternalCurrent, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null) 
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PossiblyCaptureContext(ref stackMark);
        } 

        ///  
        /// Initializes a new  with the specified action, state, snd options. 
        /// 
        /// The delegate that represents the code to execute in the task. 
        /// An object representing data to be used by the action.
        /// 
        /// 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(Action action, object state, TaskCreationOptions creationOptions)
            : this((object)action, state, Task.InternalCurrent, CancellationToken.None, creationOptions, InternalTaskOptions.None, null) 
        { 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PossiblyCaptureContext(ref stackMark); 
        }

        /// 
        /// Initializes a new  with the specified action, state, snd options. 
        /// 
        /// The delegate that represents the code to execute in the task. 
        /// An object representing data to be used by the action. 
        /// 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(Action action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) 
            : this((object)action, state, Task.InternalCurrent, cancellationToken, creationOptions, InternalTaskOptions.None, null) 
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            PossiblyCaptureContext(ref stackMark);
        }

 
        // For Task.ContinueWith() and Future.ContinueWith()
        internal Task(Action action, object state, Task parent, CancellationToken cancellationToken, 
            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark) 
            : this((object)action, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
        { 
            PossiblyCaptureContext(ref stackMark);
        }

        ///  
        /// An internal constructor used by the factory methods on task and its descendent(s).
        /// This variant does not capture the ExecutionContext; it is up to the caller to do that. 
        ///  
        /// An action to execute.
        /// Optional state to pass to the action. 
        /// Parent of Task.
        /// A CancellationToken for the task.
        /// A task scheduler under which the task will run.
        /// Options to control its execution. 
        /// Internal options to control its execution
        internal Task(object action, object state, Task parent, CancellationToken cancellationToken, 
            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) 
        {
            if (action == null) 
            {
                throw new ArgumentNullException("action");
            }
 
            Contract.Assert(action is Action || action is Action);
 
            // This is readonly, and so must be set in the constructor 
            // Keep a link to your parent if: (A) You are attached, or (B) you are self-replicating.
            // 
            if (((creationOptions & TaskCreationOptions.AttachedToParent) != 0) ||
                ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
                )
            { 
                m_parent = parent;
            } 
 
            TaskConstructorCore(action, state, cancellationToken, creationOptions, internalOptions, scheduler);
        } 

        /// 
        /// Common logic used by the following internal ctors:
        ///     Task() 
        ///     Task(object action, object state, Task parent, TaskCreationOptions options, TaskScheduler taskScheduler)
        /// 
        /// ASSUMES THAT m_creatingTask IS ALREADY SET. 
        ///
        ///  
        /// Action for task to execute.
        /// Object to which to pass to action (may be null)
        /// Task scheduler on which to run thread (only used by continuation tasks).
        /// A CancellationToken for the Task. 
        /// Options to customize behavior of Task.
        /// Internal options to customize behavior of Task. 
        internal void TaskConstructorCore(object action, object state, CancellationToken cancellationToken, 
            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
        { 
            m_action = action;
            m_stateObject = state;
            m_taskScheduler = scheduler;
 
            // Check for validity of options
            if ((creationOptions & 
                    ~(TaskCreationOptions.AttachedToParent | 
                      TaskCreationOptions.LongRunning |
                      TaskCreationOptions.PreferFairness)) != 0) 
            {
                throw new ArgumentOutOfRangeException("creationOptions");
            }
 
            if ((internalOptions &
                    ~(InternalTaskOptions.SelfReplicating | 
                      InternalTaskOptions.ChildReplica | 
                      InternalTaskOptions.PromiseTask |
                      InternalTaskOptions.ContinuationTask | 
                      InternalTaskOptions.QueuedByRuntime)) != 0)
            {
                throw new ArgumentOutOfRangeException("internalOptions", Environment.GetResourceString("Task_ctor_IllegalInternalOptions"));
            } 

 
            // Throw exception if the user specifies both LongRunning and SelfReplicating 
            if (((creationOptions & TaskCreationOptions.LongRunning) != 0) &&
                ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)) 
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_ctor_LRandSR"));
            }
 
            // Assign options to m_stateAndOptionsFlag.
            Contract.Assert(m_stateFlags == 0, "TaskConstructorCore: non-zero m_stateFlags"); 
            Contract.Assert((((int)creationOptions) | OptionsMask) == OptionsMask, "TaskConstructorCore: options take too many bits"); 
            m_stateFlags = (int)creationOptions | (int)internalOptions;
 
            // For continuation tasks or TaskCompletionSource.Tasks, begin life in WaitingForActivation state
            // rather than Created state.
            if ((m_action == null) ||
                ((internalOptions & InternalTaskOptions.ContinuationTask) != 0)) 
            {
                m_stateFlags |= TASK_STATE_WAITINGFORACTIVATION; 
            } 

            // Now is the time to add the new task to the children list 
            // of the creating task if the options call for it.
            // We can safely call the creator task's AddNewChild() method to register it,
            // because at this point we are already on its thread of execution.
 
            if (m_parent != null && (creationOptions & TaskCreationOptions.AttachedToParent) != 0)
            { 
                m_parent.AddNewChild(); 
            }
 
            // if we have a non-null cancellationToken, allocate the contingent properties to save it
            // we need to do this as the very last thing in the construction path, because the CT registration could modify m_stateFlags
            if (cancellationToken.CanBeCanceled)
            { 
                Contract.Assert((internalOptions & (InternalTaskOptions.ChildReplica | InternalTaskOptions.SelfReplicating)) == 0,
                    "TaskConstructorCore: Did not expect to see cancellable token for replica/replicating task."); 
                LazyInitializer.EnsureInitialized(ref m_contingentProperties, s_contingentPropertyCreator); 
                m_contingentProperties.m_cancellationToken = cancellationToken;
 
                try
                {
                    cancellationToken.ThrowIfSourceDisposed();
 
                    // If an unstarted task has a valid CancellationToken that gets signalled while the task is still not queued
                    // we need to proactively cancel it, because it may never execute to transition itself. 
                    // The only way to accomplish this is to register a callback on the CT. 
                    // We exclude Promise tasks from this, because TasckCompletionSource needs to fully control the inner tasks's lifetime (i.e. not allow external cancellations)
                    if ((internalOptions & 
                        (InternalTaskOptions.QueuedByRuntime | InternalTaskOptions.PromiseTask)) == 0)
                    {
                        CancellationTokenRegistration ctr = cancellationToken.InternalRegisterWithoutEC(s_taskCancelCallback, this);
                        m_contingentProperties.m_cancellationRegistration = new Shared(ctr); 
                    }
                } 
                catch 
                {
                    // If we have an exception related to our CancellationToken, then we need to subtract ourselves 
                    // from our parent before throwing it.
                    if ((m_parent != null) && ((creationOptions & TaskCreationOptions.AttachedToParent) != 0))
                        m_parent.DisregardChild();
                    throw; 
                }
            } 
        } 

        ///  
        /// Checks if we registered a CT callback during construction, and deregisters it.
        /// This should be called when we know the registration isn't useful anymore. Specifically from Finish() if the task has completed
        /// successfully or with an exception.
        ///  
        internal void DeregisterCancellationCallback()
        { 
            if (m_contingentProperties != null && 
                m_contingentProperties.m_cancellationRegistration != null)
            { 
                // Harden against ODEs thrown from disposing of the CTR.
                // Since the task has already been put into a final state by the time this
                // is called, all we can do here is suppress the exception.
                try 
                {
                    m_contingentProperties.m_cancellationRegistration.Value.Dispose(); 
                } 
                catch (ObjectDisposedException) { }
 
                m_contingentProperties.m_cancellationRegistration = null;
            }
        }
 

        // Static delegate to be used as a cancellation callback on unstarted tasks that have a valid cancellation token. 
        // This is necessary to transition them into canceled state if their cancellation token is signalled while they are still not queued 
        internal static Action s_taskCancelCallback = new Action(TaskCancelCallback);
        private static void TaskCancelCallback(Object o) 
        {
            Task t = (Task)o;
            t.InternalCancel(false);
        } 

        // Debugger support 
        private string DebuggerDisplayMethodDescription 
        {
            get 
            {
                Delegate d = (Delegate)m_action;
                return d != null ? d.Method.ToString() : "{null}";
            } 
        }
 
 
        /// 
        /// Captures the ExecutionContext so long as flow isn't suppressed. 
        /// 
        /// A stack crawl mark pointing to the frame of the caller.

        [SecuritySafeCritical] 
        internal void PossiblyCaptureContext(ref StackCrawlMark stackMark)
        { 
            if (!ExecutionContext.IsFlowSuppressed()) 
            {
                // In the legacy .NET 3.5 build, we don't have the optimized overload of Capture() 
                // available, so we call the parameterless overload.
#if PFX_LEGACY_3_5
                m_capturedContext = ExecutionContext.Capture();
#else 
                m_capturedContext = ExecutionContext.Capture(
                    ref stackMark, 
                    ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase); 
#endif
            } 
        }

        // Internal property to process TaskCreationOptions access and mutation.
        internal TaskCreationOptions Options 
        {
            get 
            { 
                Contract.Assert((OptionsMask & 1) == 1, "OptionsMask needs a shift in Options.get");
                return (TaskCreationOptions)(m_stateFlags & OptionsMask); 
            }
        }

        // Atomically OR-in newBits to m_stateFlags, while making sure that 
        // no illegalBits are set.  Returns true on success, false on failure.
        internal bool AtomicStateUpdate(int newBits, int illegalBits) 
        { 
            int oldFlags = 0;
            return AtomicStateUpdate(newBits, illegalBits, ref oldFlags); 
        }

        internal bool AtomicStateUpdate(int newBits, int illegalBits, ref int oldFlags)
        { 
            SpinWait sw = new SpinWait();
 
            do 
            {
                oldFlags = m_stateFlags; 
                if ((oldFlags & illegalBits) != 0) return false;
                if (Interlocked.CompareExchange(ref m_stateFlags, oldFlags | newBits, oldFlags) == oldFlags)
                {
                    return true; 
                }
                sw.SpinOnce(); 
            } while (true); 

        } 

        // Atomically mark a Task as started while making sure that it is not canceled.
        internal bool MarkStarted()
        { 
            return AtomicStateUpdate(TASK_STATE_STARTED, TASK_STATE_CANCELED | TASK_STATE_STARTED);
        } 
 

        ///  
        /// Internal function that will be called by a new child task to add itself to
        /// the children list of the parent (this).
        ///
        /// Since a child task can only be created from the thread executing the action delegate 
        /// of this task, reentrancy is neither required nor supported. This should not be called from
        /// anywhere other than the task construction/initialization codepaths. 
        ///  
        internal void AddNewChild()
        { 
            Contract.Assert(Task.InternalCurrent == this || this.IsSelfReplicatingRoot, "Task.AddNewChild(): Called from an external context");

            LazyInitializer.EnsureInitialized(ref m_contingentProperties, s_contingentPropertyCreator);
 

            if (m_contingentProperties.m_completionCountdown == 1 && !IsSelfReplicatingRoot) 
            { 
                // A count of 1 indicates so far there was only the parent, and this is the first child task
                // Single kid => no fuss about who else is accessing the count. Let's save ourselves 100 cycles 
                // We exclude self replicating root tasks from this optimization, because further child creation can take place on
                // other cores and with bad enough timing this write may not be visible to them.
                m_contingentProperties.m_completionCountdown++;
            } 
            else
            { 
                // otherwise do it safely 
                Interlocked.Increment(ref m_contingentProperties.m_completionCountdown);
            } 
        }

        // This is called in the case where a new child is added, but then encounters a CancellationToken-related exception.
        // We need to subtract that child from m_completionCountdown, or the parent will never complete. 
        internal void DisregardChild()
        { 
            Contract.Assert(Task.InternalCurrent == this, "Task.DisregardChild(): Called from an external context"); 
            Contract.Assert((m_contingentProperties != null) && (m_contingentProperties.m_completionCountdown >= 2), "Task.DisregardChild(): Expected parent count to be >= 2");
 
            Interlocked.Decrement(ref m_contingentProperties.m_completionCountdown);
        }

        ///  
        /// Starts the , scheduling it for execution to the current TaskScheduler. 
        ///  
        /// 
        /// A task may only be started and run only once.  Any attempts to schedule a task a second time 
        /// will result in an exception.
        /// 
        /// 
        /// The  is not in a valid state to be started. It may have already been started, 
        /// executed, or canceled, or it may have been created in a manner that doesn't support direct
        /// scheduling. 
        ///  
        /// 
        /// The  instance has been disposed. 
        /// 
        public void Start()
        {
            Start(TaskScheduler.Current); 
        }
 
        ///  
        /// Starts the , scheduling it for execution to the specified TaskScheduler. 
        /// 
        /// 
        /// A task may only be started and run only once. Any attempts to schedule a task a second time will
        /// result in an exception. 
        /// 
        ///  
        /// The TaskScheduler with which to associate 
        /// and execute this task.
        ///  
        /// 
        /// The  argument is null.
        /// 
        ///  
        /// The  is not in a valid state to be started. It may have already been started,
        /// executed, or canceled, or it may have been created in a manner that doesn't support direct 
        /// scheduling. 
        /// 
        ///  
        /// The  instance has been disposed.
        /// 
        public void Start(TaskScheduler scheduler)
        { 
            // Throw an exception if the task has previously been disposed.
            ThrowIfDisposed(); 
 
            // Need to check this before (m_action == null) because completed tasks will
            // set m_action to null.  We would want to know if this is the reason that m_action == null. 
            if (IsCompleted)
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_Start_TaskCompleted"));
            } 

            if (m_action == null) 
            { 
                throw new InvalidOperationException(Environment.GetResourceString("Task_Start_NullAction"));
            } 

            if (scheduler == null)
            {
                throw new ArgumentNullException("scheduler"); 
            }
 
            if ((Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) != 0) 
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_Start_ContinuationTask")); 
            }


            // Make sure that Task only gets started once.  Or else throw an exception. 
            if (Interlocked.CompareExchange(ref m_taskScheduler, scheduler, null) != null)
            { 
                throw new InvalidOperationException(Environment.GetResourceString("Task_Start_AlreadyStarted")); 
            }
 
            ScheduleAndStart(true);
        }

        ///  
        /// Runs the  synchronously on the current TaskScheduler. 
        ///  
        /// 
        ///  
        /// A task may only be started and run only once. Any attempts to schedule a task a second time will
        /// result in an exception.
        /// 
        ///  
        /// Tasks executed with  will be associated with the current TaskScheduler. 
        ///  
        /// 
        /// If the target scheduler does not support running this Task on the current thread, the Task will 
        /// be scheduled for execution on the scheduler, and the current thread will block until the
        /// Task has completed execution.
        /// 
        ///  
        /// 
        /// The  is not in a valid state to be started. It may have already been started, 
        /// executed, or canceled, or it may have been created in a manner that doesn't support direct 
        /// scheduling.
        ///  
        /// 
        /// The  instance has been disposed.
        /// 
        public void RunSynchronously() 
        {
            InternalRunSynchronously(TaskScheduler.Current); 
        } 

        ///  
        /// Runs the  synchronously on the scheduler provided.
        /// 
        ///  
        /// 
        /// A task may only be started and run only once. Any attempts to schedule a task a second time will 
        /// result in an exception. 
        /// 
        ///  
        /// If the target scheduler does not support running this Task on the current thread, the Task will
        /// be scheduled for execution on the scheduler, and the current thread will block until the
        /// Task has completed execution.
        ///  
        /// 
        ///  
        /// The  is not in a valid state to be started. It may have already been started, 
        /// executed, or canceled, or it may have been created in a manner that doesn't support direct
        /// scheduling. 
        /// 
        /// 
        /// The  instance has been disposed.
        ///  
        /// The  parameter
        /// is null. 
        /// The scheduler on which to attempt to run this task inline. 
        public void RunSynchronously(TaskScheduler scheduler)
        { 
            if (scheduler == null)
            {
                throw new ArgumentNullException("scheduler");
            } 

            InternalRunSynchronously(scheduler); 
        } 

        // 
        // Internal version of RunSynchronously that allows a taskScheduler argument.
        //
        [SecuritySafeCritical] // Needed for QueueTask
        internal void InternalRunSynchronously(TaskScheduler scheduler) 
        {
            Contract.Assert(scheduler != null, "Task.InternalRunSynchronously(): null TaskScheduler"); 
            ThrowIfDisposed(); 

            // Can't call this method on a continuation task 
            if ((Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) != 0)
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_Continuation"));
            } 

            // Can't call this method on a task that has already completed 
            if (IsCompleted) 
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_TaskCompleted")); 
            }

            // Can't call this method on a promise-style task
            if (m_action == null) 
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_Promise")); 
            } 

            // Make sure that Task only gets started once.  Or else throw an exception. 
            if (Interlocked.CompareExchange(ref m_taskScheduler, scheduler, null) != null)
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_AlreadyStarted"));
            } 

            // execute only if we win the ---- against concurrent cancel attempts. 
            // otherwise throw an exception, because we've been canceled. 
            if (MarkStarted())
            { 
                bool taskQueued = false;
                try
                {
                    // We wrap TryRunInline() in a try/catch block and move an excepted task to Faulted here, 
                    // but not in Wait()/WaitAll()/FastWaitAll().  Here, we know for sure that the
                    // task will not be subsequently scheduled (assuming that the scheduler adheres 
                    // to the guideline that an exception implies that no state change took place), 
                    // so it is safe to catch the exception and move the task to a final state.  The
                    // same cannot be said for Wait()/WaitAll()/FastWaitAll(). 
                    if (!scheduler.TryRunInline(this, false))
                    {
                        scheduler.QueueTask(this);
                        taskQueued = true; // only mark this after successfully queuing the task. 
                    }
 
                    // A successful TryRunInline doesn't guarantee completion, as there may be unfinished children 
                    // Also if we queued the task above, we need to wait.
                    if (!IsCompleted) 
                    {
                        CompletedEvent.Wait();
                    }
                } 
                catch (Exception e)
                { 
                    // we 1) either received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown 
                    //    2) or a a ThreadAbortException, which we need to skip here, because it would already have been handled in Task.Execute
                    if (!taskQueued && !(e is ThreadAbortException)) 
                    {
                        // We had a problem with TryRunInline() or QueueTask().
                        // Record the exception, marking ourselves as Completed/Faulted.
                        TaskSchedulerException tse = new TaskSchedulerException(e); 
                        AddException(tse);
                        Finish(false); 
 
                        // Mark ourselves as "handled" to avoid crashing the finalizer thread if the caller neglects to
                        // call Wait() on this task. 
                        // m_contingentProperties.m_exceptionHolder *should* already exist after AddException()
                        Contract.Assert((m_contingentProperties != null) && (m_contingentProperties.m_exceptionsHolder != null),
                            "Task.InternalRunSynchronously(): Expected m_contingentProperties.m_exceptionsHolder to exist");
                        m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false); 

                        // And re-throw. 
                        throw tse; 
                    }
                    else 
                    {
                        // We had a problem with CompletedEvent.Wait().  Just re-throw.
                        throw;
                    } 
                }
            } 
            else 
            {
                Contract.Assert((m_stateFlags & TASK_STATE_CANCELED) != 0, "Task.RunSynchronously: expected TASK_STATE_CANCELED to be set"); 
                // Can't call this method on canceled task.
                throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_TaskCompleted"));
            }
        } 

 
        //// 
        //// Helper methods for Factory StartNew methods.
        //// 


        // Implicitly converts action to object and handles the meat of the StartNew() logic.
        internal static Task InternalStartNew( 
            Task creatingTask, object action, object state, CancellationToken cancellationToken, TaskScheduler scheduler,
            TaskCreationOptions options, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark) 
        { 
            // Validate arguments.
            if (scheduler == null) 
            {
                throw new ArgumentNullException("scheduler");
            }
 
            // Create and schedule the task. This throws an InvalidOperationException if already shut down.
            // Here we add the InternalTaskOptions.QueuedByRuntime to the internalOptions, so that TaskConstructorCore can skip the cancellation token registration 
            Task t = new Task(action, state, creatingTask, cancellationToken, options, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); 
            t.PossiblyCaptureContext(ref stackMark);
 
            t.ScheduleAndStart(false);
            return t;
        }
 
        // Variant of InternalStartNew that takes an existing context.
        internal static Task InternalStartNew( 
            Task creatingTask, object action, object state, TaskScheduler scheduler, TaskCreationOptions options, 
            InternalTaskOptions internalOptions, ExecutionContext context)
        { 
            // Validate arguments.
            if (scheduler == null)
            {
                throw new ArgumentNullException("scheduler"); 
            }
 
            // Create and schedule the task. This throws an InvalidOperationException if already shut down. 

            // Here we add the InternalTaskOptions.QueuedByRuntime to the task's options, so that TaskConstructorCore can skip the cancellation token registration 
            Task t = new Task(action, state, creatingTask, CancellationToken.None, options, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
            t.m_capturedContext = context;

            t.ScheduleAndStart(false); 
            return t;
        } 
 

 
        /////////////
        // properties

        ///  
        /// Gets a unique ID for this Task instance.
        ///  
        ///  
        /// Task IDs are assigned on-demand and do not necessarily represent the order in the which Task
        /// instances were created. 
        /// 
        public int Id
        {
            get 
            {
                if (m_taskId == 0) 
                { 
                    int newId = 0;
                    // We need to repeat if Interlocked.Increment wraps around and returns 0. 
                    // Otherwise next time this task's Id is queried it will get a new value
                    do
                    {
                        newId = Interlocked.Increment(ref s_taskIdCounter); 
                    }
                    while (newId == 0); 
 
                    Interlocked.CompareExchange(ref m_taskId, newId, 0);
                } 

                return m_taskId;
            }
        } 

        ///  
        /// Returns the unique ID of the currently executing Task. 
        /// 
        public static int? CurrentId 
        {
            get
            {
                Task currentTask = InternalCurrent; 
                if (currentTask != null)
                    return currentTask.Id; 
                else 
                    return null;
            } 
        }

        /// 
        /// Gets the Task instance currently executing, or 
        /// null if none exists.
        ///  
        internal static Task InternalCurrent 
        {
            get { return ThreadLocals.s_currentTask; } 
        }

        /// 
        /// Gets the StackGuard object assigned to the current thread. 
        /// 
        internal static StackGuard CurrentStackGuard 
        { 
            get
            { 
                StackGuard sg = ThreadLocals.s_stackGuard;
                if (sg == null)
                {
                    sg = new StackGuard(); 
                    ThreadLocals.s_stackGuard = sg;
                } 
 
                return sg;
            } 
        }


        ///  
        /// Gets the Exception that caused the Task to end prematurely. If the Task completed successfully or has not yet thrown any 
        /// exceptions, this will return null.
        ///  
        /// 
        /// Tasks that throw unhandled exceptions store the resulting exception and propagate it wrapped in a
        ///  in calls to Wait
        /// or in accesses to the  property.  Any exceptions not observed by the time 
        /// the Task instance is garbage collected will be propagated on the finalizer thread.
        ///  
        ///  
        /// The Task
        /// has been disposed. 
        /// 
        public AggregateException Exception
        {
            get 
            {
                AggregateException e = null; 
 
                // If you're faulted, retrieve the exception(s)
                if (IsFaulted) e = GetExceptions(false); 

                // Only return an exception in faulted state (skip manufactured exceptions)
                // A "benevolent" race condition makes it possible to return null when IsFaulted is
                // true (i.e., if IsFaulted is set just after the check to IsFaulted above). 
                Contract.Assert((e == null) || IsFaulted, "Task.Exception_get(): returning non-null value when not Faulted");
 
                return e; 
            }
        } 

        /// 
        /// Gets the TaskStatus of this Task.
        ///  
        public TaskStatus Status
        { 
            get 
            {
                TaskStatus rval; 

                // get a cached copy of the state flags.  This should help us
                // to get a consistent view of the flags if they are changing during the
                // execution of this method. 
                int sf = m_stateFlags;
 
                if ((sf & TASK_STATE_FAULTED) != 0) rval = TaskStatus.Faulted; 
                else if ((sf & TASK_STATE_CANCELED) != 0) rval = TaskStatus.Canceled;
                else if ((sf & TASK_STATE_RAN_TO_COMPLETION) != 0) rval = TaskStatus.RanToCompletion; 
                else if ((sf & TASK_STATE_WAITING_ON_CHILDREN) != 0) rval = TaskStatus.WaitingForChildrenToComplete;
                else if ((sf & TASK_STATE_DELEGATE_INVOKED) != 0) rval = TaskStatus.Running;
                else if ((sf & TASK_STATE_STARTED) != 0) rval = TaskStatus.WaitingToRun;
                else if ((sf & TASK_STATE_WAITINGFORACTIVATION) != 0) rval = TaskStatus.WaitingForActivation; 
                else rval = TaskStatus.Created;
 
                return rval; 
            }
        } 

        /// 
        /// Gets whether this Task instance has completed
        /// execution due to being canceled. 
        /// 
        ///  
        /// A Task will complete in Canceled state either if its CancellationToken 
        /// was marked for cancellation before the task started executing, or if the task acknowledged the cancellation request on
        /// its already signaled CancellationToken by throwing an 
        /// OperationCanceledException that bears the same
        /// CancellationToken.
        /// 
        public bool IsCanceled 
        {
            get 
            { 
                // Return true if canceled bit is set and faulted bit is not set
                return (m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_FAULTED)) == TASK_STATE_CANCELED; 
            }
        }

        ///  
        /// Returns true if this task has a cancellation token and it was signaled.
        /// To be used internally in execute entry codepaths. 
        ///  
        internal bool IsCancellationRequested
        { 
            get
            {
                // check both the internal cancellation request flag and the CancellationToken attached to this task
                return ((m_contingentProperties != null) && (m_contingentProperties.m_internalCancellationRequested == CANCELLATION_REQUESTED)) || 
                    CancellationToken.IsCancellationRequested;
            } 
        } 

        // Static delegate used for creating a ContingentProperties object from LazyInitializer. 
        internal static Func s_contingentPropertyCreator = new Func(ContingentPropertyCreator);
        private static ContingentProperties ContingentPropertyCreator()
        {
            return new ContingentProperties(); 
        }
 
        ///  
        /// This internal property provides access to the CancellationToken that was set on the task
        /// when it was constructed. 
        /// 
        internal CancellationToken CancellationToken
        {
            get 
            {
                return (m_contingentProperties == null) ? CancellationToken.None : 
                                                            m_contingentProperties.m_cancellationToken; 
            }
        } 

        /// 
        /// Gets whether this  threw an OperationCanceledException while its CancellationToken was signaled.
        ///  
        internal bool IsCancellationAcknowledged
        { 
            get { return (m_stateFlags & TASK_STATE_CANCELLATIONACKNOWLEDGED) != 0; } 
        }
 

        /// 
        /// Gets whether this Task has completed.
        ///  
        /// 
        ///  will return true when the Task is in one of the three 
        /// final states: RanToCompletion, 
        /// Faulted, or
        /// Canceled. 
        /// 
        public bool IsCompleted
        {
            get 
            {
                return ((m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_FAULTED | TASK_STATE_RAN_TO_COMPLETION)) != 0); 
            } 
        }
 
        // For use in InternalWait -- marginally faster than (Task.Status == TaskStatus.RanToCompletion)
        internal bool CompletedSuccessfully
        {
            get 
            {
                int completedMask = TASK_STATE_CANCELED | TASK_STATE_FAULTED | TASK_STATE_RAN_TO_COMPLETION; 
                return (m_stateFlags & completedMask) == TASK_STATE_RAN_TO_COMPLETION; 
            }
        } 

        /// 
        /// Checks whether this task has been disposed.
        ///  
        internal bool IsDisposed
        { 
            get { return (m_stateFlags & TASK_STATE_DISPOSED) != 0; } 
        }
 
        /// 
        /// Throws an exception if the task has been disposed, and hence can no longer be accessed.
        /// 
        /// The task has been disposed. 
        internal void ThrowIfDisposed()
        { 
            if (IsDisposed) 
            {
                throw new ObjectDisposedException(null, Environment.GetResourceString("Task_ThrowIfDisposed")); 
            }
        }

 
        /// 
        /// Gets the TaskCreationOptions used 
        /// to create this task. 
        /// 
        public TaskCreationOptions CreationOptions 
        {
            get { return Options & (TaskCreationOptions)(~InternalTaskOptions.InternalOptionsMask); }
        }
 
        /// 
        /// Gets a  that can be used to wait for the task to 
        /// complete. 
        /// 
        ///  
        /// Using the wait functionality provided by 
        /// should be preferred over using  for similar
        /// functionality.
        ///  
        /// 
        /// The  has been disposed. 
        ///  
        WaitHandle IAsyncResult.AsyncWaitHandle
        { 
            // Although a slim event is used internally to avoid kernel resource allocation, this function
            // forces allocation of a true WaitHandle when called.
            get
            { 
                ThrowIfDisposed();
                return CompletedEvent.WaitHandle; 
            } 
        }
 
        // Overridden by Task to return m_futureState
        internal virtual object InternalAsyncState
        {
            get { return m_stateObject; } 
        }
 
        ///  
        /// Gets the state object supplied when the Task was created,
        /// or null if none was supplied. 
        /// 
        public object AsyncState
        {
            get { return InternalAsyncState; } 
        }
 
        ///  
        /// Gets an indication of whether the asynchronous operation completed synchronously.
        ///  
        /// true if the asynchronous operation completed synchronously; otherwise, false.
        bool IAsyncResult.CompletedSynchronously
        {
            get 
            {
                // @ 
 
                return false;
            } 
        }

        // @
 

 
        internal TaskScheduler ExecutingTaskScheduler 
        {
            get { return m_taskScheduler; } 
        }

        /// 
        /// Provides access to factory methods for creating  and  instances. 
        /// 
        ///  
        /// The factory returned from  is a default instance 
        /// of , as would result from using
        /// the default constructor on TaskFactory. 
        /// 
        public static TaskFactory Factory { get { return s_factory; } }

        ///  
        /// Provides an event that can be used to wait for completion.
        /// Only called by Wait*(), which means that we really do need to instantiate a completion event. 
        ///  
        internal ManualResetEventSlim CompletedEvent
        { 
            get
            {
                if (m_completionEvent == null)
                { 
                    bool wasCompleted = IsCompleted;
                    ManualResetEventSlim newMre = new ManualResetEventSlim(wasCompleted); 
                    if (Interlocked.CompareExchange(ref m_completionEvent, newMre, null) != null) 
                    {
                        // We lost the ----, so we will just close the event right away. 
                        newMre.Dispose();
                    }
                    else if (!wasCompleted && IsCompleted)
                    { 
                        // We published the event as unset, but the task has subsequently completed.
                        // Set the event's state properly so that callers don't deadlock. 
                        newMre.Set(); 
                    }
                } 

                return m_completionEvent;
            }
        } 

        ///  
        /// Sets the internal completion event. 
        /// 
        private void SetCompleted() 
        {

            ManualResetEventSlim mres = m_completionEvent;
            if (mres != null) 
            {
                mres.Set(); 
            } 
        }
 
        /// 
        /// Determines whether this is the root task of a self replicating group.
        /// 
        internal bool IsSelfReplicatingRoot 
        {
            get 
            { 
                return ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0) &&
                        ((Options & (TaskCreationOptions)InternalTaskOptions.ChildReplica) == 0); 
            }
        }

        ///  
        /// Determines whether the task is a replica itself.
        ///  
        internal bool IsChildReplica 
        {
            get { return (Options & (TaskCreationOptions)InternalTaskOptions.ChildReplica) != 0; } 
        }

        internal int ActiveChildCount
        { 
            get { return m_contingentProperties != null ? m_contingentProperties.m_completionCountdown - 1 : 0; }
        } 
 
        /// 
        /// The property formerly known as IsFaulted. 
        /// 
        internal bool ExceptionRecorded
        {
            get { return (m_contingentProperties != null) && (m_contingentProperties.m_exceptionsHolder != null); } 
        }
 
        ///  
        /// Gets whether the  completed due to an unhandled exception.
        ///  
        /// 
        /// If  is true, the Task's  will be equal to
        /// TaskStatus.Faulted, and its
        ///  property will be non-null. 
        /// 
        public bool IsFaulted 
        { 
            get
            { 
                // Faulted is "king" -- if that bit is present (regardless of other bits), we are faulted.
                return ((m_stateFlags & TASK_STATE_FAULTED) != 0);
            }
        } 

 
#if DEBUG 
        /// 
        /// Retrieves an identifier for the task. 
        /// 
        internal int InternalId
        {
            get { return GetHashCode(); } 
        }
#endif 
 
        /////////////
        // methods 


        /// 
        /// Disposes the , releasing all of its unmanaged resources. 
        /// 
        ///  
        /// Unlike most of the members of , this method is not thread-safe. 
        /// Also,  may only be called on a  that is in one of
        /// the final states: RanToCompletion, 
        /// Faulted, or
        /// Canceled.
        /// 
        ///  
        /// The exception that is thrown if the  is not in
        /// one of the final states: RanToCompletion, 
        /// Faulted, or 
        /// Canceled.
        ///  
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this); 
        }
 
        ///  
        /// Disposes the , releasing all of its unmanaged resources.
        ///  
        /// 
        /// A Boolean value that indicates whether this method is being called due to a call to .
        ///  
        /// 
        /// Unlike most of the members of , this method is not thread-safe. 
        ///  
        protected virtual void Dispose(bool disposing)
        { 
            if (disposing)
            {
                // Task must be completed to dispose
                if (!IsCompleted) 
                {
                    throw new InvalidOperationException(Environment.GetResourceString("Task_Dispose_NotCompleted")); 
                } 

                var tmp = m_completionEvent; // make a copy to protect against racing Disposes. 

                // Dispose of the underlying completion event
                if (tmp != null)
                { 
                    // In the unlikely event that our completion event is inflated but not yet signaled,
                    // go ahead and signal the event.  If you dispose of an unsignaled MRES, then any waiters 
                    // will deadlock; an ensuing Set() will not wake them up.  In the event of an AppDomainUnload, 
                    // there is no guarantee that anyone else is going to signal the event, and it does no harm to
                    // call Set() twice on m_completionEvent. 
                    if (!tmp.IsSet) tmp.Set();

                    tmp.Dispose();
                    m_completionEvent = null; 
                }
 
            } 

            // We OR the flags to indicate the object has been disposed.  This is not 
            // thread-safe -- trying to dispose while a task is running can lead to corruption.
            // Do this regardless of the value of "disposing".
            m_stateFlags |= TASK_STATE_DISPOSED;
        } 

        ///////////// 
        // internal helpers 

 
        /// 
        /// Schedules the task for execution.
        /// 
        /// If true, TASK_STATE_STARTED bit is turned on in 
        /// an atomic fashion, making sure that TASK_STATE_CANCELED does not get set
        /// underneath us.  If false, TASK_STATE_STARTED bit is OR-ed right in.  This 
        /// allows us to streamline things a bit for StartNew(), where competing cancellations 
        /// are not a problem.
        [SecuritySafeCritical] // Needed for QueueTask 
        internal void ScheduleAndStart(bool needsProtection)
        {
            Contract.Assert(m_taskScheduler != null, "expected a task scheduler to have been selected");
            Contract.Assert((m_stateFlags & TASK_STATE_STARTED) == 0, "task has already started"); 

            // Set the TASK_STATE_STARTED bit 
            if (needsProtection) 
            {
                if (!MarkStarted()) 
                {
                    // A cancel has snuck in before we could get started.  Quietly exit.
                    return;
                } 
            }
            else 
            { 
                m_stateFlags |= TASK_STATE_STARTED;
            } 

            try
            {
                // Queue to the indicated scheduler. 
                m_taskScheduler.QueueTask(this);
            } 
            catch (ThreadAbortException tae) 
            {
                AddException(tae); 
                FinishThreadAbortedTask(true, false);
            }
            catch (Exception e)
            { 
                // The scheduler had a problem queueing this task.  Record the exception, leaving this task in
                // a Faulted state. 
                TaskSchedulerException tse = new TaskSchedulerException(e); 
                AddException(tse);
                Finish(false); 

                // Now we need to mark ourselves as "handled" to avoid crashing the finalizer thread if we are called from StartNew()
                // or from the self replicating logic, because in both cases the exception is either propagated outside directly, or added
                // to an enclosing parent. However we won't do this for continuation tasks, because in that case we internally eat the exception 
                // and therefore we need to make sure the user does later observe it explicitly or see it on the finalizer.
 
                if ((Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0) 
                {
                    // m_contingentProperties.m_exceptionHolder *should* already exist after AddException() 
                    Contract.Assert((m_contingentProperties != null) && (m_contingentProperties.m_exceptionsHolder != null),
                            "Task.InternalRunSynchronously(): Expected m_contingentProperties.m_exceptionsHolder to exist");

                    m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false); 
                }
 
                // re-throw the exception wrapped as a TaskSchedulerException. 
                throw tse;
            } 
        }


        ///  
        /// Adds an exception to the list of exceptions this task has thrown.
        ///  
        /// An object representing either an Exception or a collection of Exceptions. 
        internal void AddException(object exceptionObject)
        { 
            //
            // WARNING: A great deal of care went into insuring that
            // AddException() and GetExceptions() are never called
            // simultaneously.  See comment at start of GetExceptions(). 
            //
 
            // Lazily initialize the list, ensuring only one thread wins. 
            LazyInitializer.EnsureInitialized(ref m_contingentProperties, s_contingentPropertyCreator);
            if (m_contingentProperties.m_exceptionsHolder == null) 
            {
                TaskExceptionHolder holder = new TaskExceptionHolder(this);
                if (Interlocked.CompareExchange(
                    ref m_contingentProperties.m_exceptionsHolder, holder, null) != null) 
                {
                    // If we lost the ----, suppress finalization. 
                    holder.MarkAsHandled(false); 
                }
            } 

            // Figure this out before your enter the lock.
            Contract.Assert((exceptionObject is Exception) || (exceptionObject is IEnumerable),
                "Task.AddException: Expected an Exception or an IEnumerable"); 

            lock (m_contingentProperties) 
            { 
                m_contingentProperties.m_exceptionsHolder.Add(exceptionObject);
            } 

        }

 
        /// 
        /// Returns a list of exceptions by aggregating the holder's contents. Or null if 
        /// no exceptions have been thrown. 
        /// 
        /// Whether to include a TCE if cancelled. 
        /// An aggregate exception, or null if no exceptions have been caught.
        private AggregateException GetExceptions(bool includeTaskCanceledExceptions)
        {
            // 
            // WARNING: The Task/Task/TaskCompletionSource classes
            // have all been carefully crafted to insure that GetExceptions() 
            // is never called while AddException() is being called.  There 
            // are locks taken on m_contingentProperties in several places:
            // 
            // -- Task.TrySetException(): The lock allows the
            //    task to be set to Faulted state, and all exceptions to
            //    be recorded, in one atomic action.
            // 
            // -- Task.Exception_get(): The lock ensures that Task.TrySetException()
            //    is allowed to complete its operation before Task.Exception_get() 
            //    can access GetExceptions(). 
            //
            // -- Task.ThrowIfExceptional(): The lock insures that Wait() will 
            //    not attempt to call GetExceptions() while Task.TrySetException()
            //    is in the process of calling AddException().
            //
            // For "regular" tasks, we effectively keep AddException() and GetException() 
            // from being called concurrently by the way that the state flows.  Until
            // a Task is marked Faulted, Task.Exception_get() returns null.  And 
            // a Task is not marked Faulted until it and all of its children have 
            // completed, which means that all exceptions have been recorded.
            // 
            // It might be a lot easier to follow all of this if we just required
            // that all calls to GetExceptions() and AddExceptions() were made
            // under a lock on m_contingentProperties.  But that would also
            // increase our lock occupancy time and the frequency with which we 
            // would need to take the lock.
            // 
            // If you add a call to GetExceptions() anywhere in the code, 
            // please continue to maintain the invariant that it can't be
            // called when AddException() is being called. 
            //

            // We'll lazily create a TCE if the task has been canceled.
            Exception canceledException = null; 
            if (includeTaskCanceledExceptions && IsCanceled)
            { 
                canceledException = new TaskCanceledException(this); 
            }
 
            if (ExceptionRecorded)
            {
                // There are exceptions; get the aggregate and optionally add the canceled
                // exception to the aggregate (if applicable). 
                Contract.Assert(m_contingentProperties != null); // ExceptionRecorded ==> m_contingentProperties != null
 
                // No need to lock around this, as other logic prevents the consumption of exceptions 
                // before they have been completely processed.
                return m_contingentProperties.m_exceptionsHolder.CreateExceptionObject(false, canceledException); 
            }
            else if (canceledException != null)
            {
                // No exceptions, but there was a cancelation. Aggregate and return it. 
                return new AggregateException(canceledException);
            } 
 
            return null;
        } 

        /// 
        /// Throws an aggregate exception if the task contains exceptions.
        ///  
        internal void ThrowIfExceptional(bool includeTaskCanceledExceptions)
        { 
            Contract.Assert(IsCompleted, "ThrowIfExceptional(): Expected IsCompleted == true"); 

            Exception exception = GetExceptions(includeTaskCanceledExceptions); 
            if (exception != null)
            {
                UpdateExceptionObservedStatus();
                throw exception; 
            }
        } 
 
        /// 
        /// Checks whether this is an attached task, and whether we are being called by the parent task. 
        /// And sets the TASK_STATE_EXCEPTIONOBSERVEDBYPARENT status flag based on that.
        ///
        /// This is meant to be used internally when throwing an exception, and when WaitAll is gathering
        /// exceptions for tasks it waited on. If this flag gets set, the implicit wait on children 
        /// will skip exceptions to prevent duplication.
        /// 
        /// This should only be called when this task has completed with an exception 
        ///
        ///  
        internal void UpdateExceptionObservedStatus()
        {
            if ((Options & TaskCreationOptions.AttachedToParent) != 0 &&
                 Task.InternalCurrent == m_parent) 
            {
                m_stateFlags |= TASK_STATE_EXCEPTIONOBSERVEDBYPARENT; 
            } 
        }
 
        /// 
        /// Checks whether the TASK_STATE_EXCEPTIONOBSERVEDBYPARENT status flag is set,
        /// This will only be used by the implicit wait to prevent double throws
        /// 
        /// 
        internal bool IsExceptionObservedByParent 
        { 
            get
            { 
                return (m_stateFlags & TASK_STATE_EXCEPTIONOBSERVEDBYPARENT) != 0;
            }
        }
 
        /// 
        /// Checks whether the body was ever invoked. Used by task scheduler code to verify custom schedulers actually ran the task. 
        ///  
        internal bool IsDelegateInvoked
        { 
            get
            {
                return (m_stateFlags & TASK_STATE_DELEGATE_INVOKED) != 0;
            } 
        }
 
        ///  
        /// Signals completion of this particular task.
        /// 
        /// The bUserDelegateExecuted parameter indicates whether this Finish() call comes following the
        /// full execution of the user delegate.
        ///
        /// If bUserDelegateExecuted is false, it mean user delegate wasn't invoked at all (either due to 
        /// a cancellation request, or because this task is a promise style Task). In this case, the steps
        /// involving child tasks (i.e. WaitForChildren) will be skipped. 
        /// 
        /// 
        internal void Finish(bool bUserDelegateExecuted) 
        {

            if (!bUserDelegateExecuted)
            { 
                // delegate didn't execute => no children. We can safely call the remaining finish stages
                FinishStageTwo(); 
            } 
            else
            { 
                ContingentProperties properties = m_contingentProperties;

                if (properties == null ||                    // no contingent properties, no children. Safe to complete ourselves
                    (properties.m_completionCountdown == 1 && !IsSelfReplicatingRoot) || 
                    // Count of 1 => either all children finished, or there were none. Safe to complete ourselves
                    // without paying the price of an Interlocked.Decrement. 
                    // However we need to exclude self replicating root tasks from this optimization, because 
                    // they can have children joining in, or finishing even after the root task delegate is done.
                    Interlocked.Decrement(ref properties.m_completionCountdown) == 0) // Reaching this sub clause means there may be remaining active children, 
                // and we could be racing with one of them to call FinishStageTwo().
                // So whoever does the final Interlocked.Dec is responsible to finish.
                {
 
                    FinishStageTwo();
                } 
                else 
                {
                    // Apparently some children still remain. It will be up to the last one to process the completion of this task on their own thread. 
                    // We will now yield the thread back to ThreadPool. Mark our state appropriately before getting out.

                    // We have to use an atomic update for this and make sure not to overwrite a final state,
                    // because at this very moment the last child's thread may be concurrently completing us. 
                    // Otherwise we risk overwriting the TASK_STATE_RAN_TO_COMPLETION, _CANCELED or _FAULTED bit which may have been set by that child task.
                    // Note that the concurrent update by the last child happening in FinishStageTwo could still wipe out the TASK_STATE_WAITING_ON_CHILDREN flag, 
                    // but it is not critical to maintain, therefore we dont' need to intruduce a full atomic update into FinishStageTwo 

                    AtomicStateUpdate(TASK_STATE_WAITING_ON_CHILDREN, TASK_STATE_FAULTED | TASK_STATE_CANCELED | TASK_STATE_RAN_TO_COMPLETION); 
                }
            }

            // Now is the time to prune exceptional children. We'll walk the list and removes the ones whose exceptions we might have observed after they threw. 
            // we use a local variable for exceptional children here because some other thread may be nulling out m_contingentProperties.m_exceptionalChildren
            List exceptionalChildren = m_contingentProperties != null ? m_contingentProperties.m_exceptionalChildren : null; 
 
            if (exceptionalChildren != null)
            { 
                lock (exceptionalChildren)
                {
                    exceptionalChildren.RemoveAll(s_IsExceptionObservedByParentPredicate); // RemoveAll has better performance than doing it ourselves
                } 
            }
        } 
 
        // statically allocated delegate for the removeall expression in Finish()
        private static Predicate s_IsExceptionObservedByParentPredicate = new Predicate((t) => { return t.IsExceptionObservedByParent; }); 

        /// 
        /// FinishStageTwo is to be executed as soon as we known there are no more children to complete.
        /// It can happen i) either on the thread that originally executed this task (if no children were spawned, or they all completed by the time this task's delegate quit) 
        ///              ii) or on the thread that executed the last child.
        ///  
        internal void FinishStageTwo() 
        {
            AddExceptionsFromChildren(); 

            // At this point, the task is done executing and waiting for its children,
            // we can transition our task to a completion state.
            int completionState; 
            if (ExceptionRecorded)
            { 
                completionState = TASK_STATE_FAULTED; 
            }
            else if (IsCancellationRequested && IsCancellationAcknowledged) 
            {
                // We transition into the TASK_STATE_CANCELED final state if the task's CT was signalled for cancellation,
                // and the user delegate acknowledged the cancellation request by throwing an OCE,
                // and the task hasn't otherwise transitioned into faulted state. (TASK_STATE_FAULTED trumps TASK_STATE_CANCELED) 
                //
                // If the task threw an OCE without cancellation being requestsed (while the CT not being in signaled state), 
                // then we regard it as a regular exception 

                completionState = TASK_STATE_CANCELED; 
            }
            else
            {
                completionState = TASK_STATE_RAN_TO_COMPLETION; 
            }
 
            // Use Interlocked.Exchange() to effect a memory fence, preventing 
            // any SetCompleted() (or later) instructions from sneak back before it.
            Interlocked.Exchange(ref m_stateFlags, m_stateFlags | completionState); 

            // Set the completion event if it's been lazy allocated.
            SetCompleted();
 
            // if we made a cancellation registration, it's now unnecessary.
            DeregisterCancellationCallback(); 
 
            // ready to run continuations and notify parent.
            FinishStageThree(); 
        }


        ///  
        /// Final stage of the task completion code path. Notifies the parent (if any) that another of its childre are done, and runs continuations.
        /// This function is only separated out from FinishStageTwo because these two operations are also needed to be called from CancellationCleanupLogic() 
        ///  
        private void FinishStageThree()
        { 
            // Notify parent if this was an attached task
            if (m_parent != null
                && (((TaskCreationOptions)(m_stateFlags & OptionsMask)) & TaskCreationOptions.AttachedToParent) != 0)
            { 
                m_parent.ProcessChildCompletion(this);
            } 
 
            // Activate continuations (if any).
            FinishContinuations(); 

            // Need this to bound the memory usage on long/infinite continuation chains
            m_action = null;
        } 

        ///  
        /// This is called by children of this task when they are completed. 
        /// 
        internal void ProcessChildCompletion(Task childTask) 
        {
            Contract.Assert(childTask.m_parent == this, "ProcessChildCompletion should only be called for a child of this task");
            Contract.Assert(childTask.IsCompleted, "ProcessChildCompletion was called for an uncompleted task");
 
            // if the child threw and we haven't observed it we need to save it for future reference
            if (childTask.IsFaulted && !childTask.IsExceptionObservedByParent) 
            { 
                // Lazily initialize the child exception list
                if (m_contingentProperties.m_exceptionalChildren == null) 
                {
                    Interlocked.CompareExchange(ref m_contingentProperties.m_exceptionalChildren, new List(), null);
                }
 
                // In rare situations involving AppDomainUnload, it's possible (though unlikely) for FinishStageTwo() to be called
                // multiple times for the same task.  In that case, AddExceptionsFromChildren() could be nulling m_exceptionalChildren 
                // out at the same time that we're processing it, resulting in a NullReferenceException here.  We'll protect 
                // ourselves by caching m_exceptionChildren in a local variable.
                List tmp = m_contingentProperties.m_exceptionalChildren; 
                if (tmp != null)
                {
                    lock (tmp)
                    { 
                        tmp.Add(childTask);
                    } 
                } 

            } 

            if (Interlocked.Decrement(ref m_contingentProperties.m_completionCountdown) == 0)
            {
                // This call came from the final child to complete, and apparently we have previously given up this task's right to complete itself. 
                // So we need to invoke the final finish stage.
 
                FinishStageTwo(); 
            }
        } 

        /// 
        /// This is to be called just before the task does its final state transition.
        /// It traverses the list of exceptional children, and appends their aggregate exceptions into this one's exception list 
        /// 
        internal void AddExceptionsFromChildren() 
        { 
            // In rare occurences during AppDomainUnload() processing, it is possible for this method to be called
            // simultaneously on the same task from two different contexts.  This can result in m_exceptionalChildren 
            // being nulled out while it is being processed, which could lead to a NullReferenceException.  To
            // protect ourselves, we'll cache m_exceptionalChildren in a local variable.
            List tmp = (m_contingentProperties != null) ? m_contingentProperties.m_exceptionalChildren : null;
 
            if (tmp != null)
            { 
                // This lock is necessary because even though AddExceptionsFromChildren is last to execute, it may still 
                // be racing with the code segment at the bottom of Finish() that prunes the exceptional child array.
                lock (tmp) 
                {
                    foreach (Task task in tmp)
                    {
                        // Ensure any exceptions thrown by children are added to the parent. 
                        // In doing this, we are implicitly marking children as being "handled".
                        Contract.Assert(task.IsCompleted, "Expected all tasks in list to be completed"); 
                        if (task.IsFaulted && !task.IsExceptionObservedByParent) 
                        {
                            TaskExceptionHolder exceptionHolder = task.m_contingentProperties.m_exceptionsHolder; 
                            Contract.Assert(exceptionHolder != null);

                            // No locking necessary since child task is finished adding exceptions
                            // and concurrent CreateExceptionObject() calls do not constitute 
                            // a concurrency hazard.
                            AddException(exceptionHolder.CreateExceptionObject(false, null)); 
                        } 
                    }
                } 

                // Reduce memory pressure by getting rid of the array
                m_contingentProperties.m_exceptionalChildren = null;
            } 
        }
 
        ///  
        /// Special purpose Finish() entry point to be used when the task delegate throws a ThreadAbortedException
        /// This makes a note in the state flags so that we avoid any costly synchronous operations in the finish codepath 
        /// such as inlined continuations
        /// 
        /// 
        /// Indicates whether the ThreadAbortException was added to this task's exception holder. 
        /// This should always be true except for the case of non-root self replicating task copies.
        ///  
        /// Whether the delegate was executed. 
        internal void FinishThreadAbortedTask(bool bTAEAddedToExceptionHolder, bool delegateRan)
        { 
            Contract.Assert(!bTAEAddedToExceptionHolder || (m_contingentProperties != null && m_contingentProperties.m_exceptionsHolder != null),
                            "FinishThreadAbortedTask() called on a task whose exception holder wasn't initialized");

            // this will only be false for non-root self replicating task copies, because all of their exceptions go to the root task. 
            if (bTAEAddedToExceptionHolder)
                m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false); 
 
            // If this method has already been called for this task, or if this task has already completed, then
            // return before actually calling Finish(). 
            if (!AtomicStateUpdate(TASK_STATE_THREAD_WAS_ABORTED,
                            TASK_STATE_THREAD_WAS_ABORTED | TASK_STATE_RAN_TO_COMPLETION | TASK_STATE_FAULTED | TASK_STATE_CANCELED))
            {
                return; 
            }
 
            Finish(delegateRan); 

        } 


        /// 
        /// Executes the task. This method will only be called once, and handles bookeeping associated with 
        /// self-replicating tasks, in addition to performing necessary exception marshaling.
        ///  
        /// The task has already been disposed. 
        private void Execute()
        { 
            if (IsSelfReplicatingRoot)
            {
                ExecuteSelfReplicating(this);
            } 
            else
            { 
                try 
                {
                    InnerInvoke(); 
                }
                catch (ThreadAbortException tae)
                {
                    // Don't record the TAE or call FinishThreadAbortedTask for a child replica task -- 
                    // it's already been done downstream.
                    if (!IsChildReplica) 
                    { 
                        // Record this exception in the task's exception list
                        HandleException(tae); 

                        // This is a ThreadAbortException and it will be rethrown from this catch clause, causing us to
                        // skip the regular Finish codepath. In order not to leave the task unfinished, we now call
                        // FinishThreadAbortedTask here. 
                        FinishThreadAbortedTask(true, true);
                    } 
                } 
                catch (Exception exn)
                { 
                    // Record this exception in the task's exception list
                    HandleException(exn);
                }
            } 
        }
 
        // Allows (internal) deriving classes to support limited replication. 
        // (By default, replication is basically unlimited).
        internal virtual bool ShouldReplicate() 
        {
            return true;
        }
 
        // Allows (internal) deriving classes to instantiate the task replica as a Task super class of their choice
        // (By default, we create a regular Task instance) 
        internal virtual Task CreateReplicaTask(Action taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler, 
                                            TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica)
        { 
            return new Task(taskReplicaDelegate, stateObject, parentTask, CancellationToken.None,
                            creationOptionsForReplica, internalOptionsForReplica, parentTask.ExecutingTaskScheduler);
        }
 
        // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
        internal virtual Object SavedStateForNextReplica 
        { 
            get { return null; }
 
            set { /*do nothing*/ }
        }

        // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica 
        internal virtual Object SavedStateFromPreviousReplica
        { 
            get { return null; } 

            set { /*do nothing*/ } 
        }

        // Allows internal deriving classes to support replicas that exit prematurely and want to hand over the child replica that they
        // had queued, so that the replacement replica can work with that child task instead of queuing up yet another one 
        internal virtual Task HandedOverChildReplica
        { 
            get { return null; } 

            set { /* do nothing*/ } 
        }

        private static void ExecuteSelfReplicating(Task root)
        { 
            TaskCreationOptions creationOptionsForReplicas = root.CreationOptions | TaskCreationOptions.AttachedToParent;
            InternalTaskOptions internalOptionsForReplicas = 
                InternalTaskOptions.ChildReplica |  // child replica flag disables self replication for the replicas themselves. 
                InternalTaskOptions.SelfReplicating |  // we still want to identify this as part of a self replicating group
                InternalTaskOptions.QueuedByRuntime;   // we queue and cancel these tasks internally, so don't allow CT registration to take place 


            // Important Note: The child replicas we launch from here will be attached the root replica (by virtue of the root.CreateReplicaTask call)
            // because we need the root task to receive all their exceptions, and to block until all of them return 

 
            // This variable is captured in a closure and shared among all replicas. 
            bool replicasAreQuitting = false;
 
            // Set up a delegate that will form the body of the root and all recursively created replicas.
            Action taskReplicaDelegate = null;
            taskReplicaDelegate = delegate
            { 
                Task currentTask = Task.InternalCurrent;
 
 
                // Check if a child task has been handed over by a prematurely quiting replica that we might be a replacement for.
                Task childTask = currentTask.HandedOverChildReplica; 

                if (childTask == null)
                {
                    // Apparently we are not a replacement task. This means we need to queue up a child task for replication to progress 

                    // Down-counts a counter in the root task. 
                    if (!root.ShouldReplicate()) return; 

                    // If any of the replicas have quit, we will do so ourselves. 
                    if (replicasAreQuitting)
                    {
                        return;
                    } 

                    // Propagate a copy of the context from the root task. It may be null if flow was suppressed. 
                    ExecutionContext creatorContext = root.m_capturedContext; 

 
                    childTask = root.CreateReplicaTask(taskReplicaDelegate, root.m_stateObject, root, root.ExecutingTaskScheduler,
                                                       creationOptionsForReplicas, internalOptionsForReplicas);

                    childTask.m_capturedContext = (creatorContext == null ? null : creatorContext.CreateCopy()); 

                    childTask.ScheduleAndStart(false); 
                } 

 

                // Finally invoke the meat of the task.
                // Note that we are directly calling root.InnerInvoke() even though we are currently be in the action delegate of a child replica
                // This is because the actual work was passed down in that delegate, and the action delegate of the child replica simply contains this 
                // replication control logic.
                try 
                { 
                    // passing in currentTask only so that the parallel debugger can find it
                    root.InnerInvokeWithArg(currentTask); 
                }
                catch (Exception exn)
                {
                    // Record this exception in the root task's exception list 
                    root.HandleException(exn);
 
                    if (exn is ThreadAbortException) 
                    {
                        // If this is a ThreadAbortException it will escape this catch clause, causing us to skip the regular Finish codepath 
                        // In order not to leave the task unfinished, we now call FinishThreadAbortedTask here
                        currentTask.FinishThreadAbortedTask(false, true);
                    }
                } 

                Object savedState = currentTask.SavedStateForNextReplica; 
 
                // check for premature exit
                if (savedState != null) 
                {
                    // the replica decided to exit early
                    // we need to queue up a replacement, attach the saved state, and yield the thread right away
 
                    Task replacementReplica = root.CreateReplicaTask(taskReplicaDelegate, root.m_stateObject, root, root.ExecutingTaskScheduler,
                                                                    creationOptionsForReplicas, internalOptionsForReplicas); 
 
                    // Propagate a copy of the context from the root task to the replacement task
                    ExecutionContext creatorContext = root.m_capturedContext; 
                    replacementReplica.m_capturedContext = (creatorContext == null ? null : creatorContext.CreateCopy());

                    replacementReplica.HandedOverChildReplica = childTask;
                    replacementReplica.SavedStateFromPreviousReplica = savedState; 

                    replacementReplica.ScheduleAndStart(false); 
                } 
                else
                { 
                    // The replica finished normally, which means it can't find more work to grab.
                    // Time to mark replicas quitting

                    replicasAreQuitting = true; 

                    // InternalCancel() could conceivably throw in the underlying scheduler's TryDequeue() method. 
                    // If it does, then make sure that we record it. 
                    try
                    { 
                        childTask.InternalCancel(true);
                    }
                    catch (Exception e)
                    { 
                        // Apparently TryDequeue threw an exception.  Before propagating that exception, InternalCancel should have
                        // attempted an atomic state transition and a call to CancellationCleanupLogic() on this task. So we know 
                        // the task was properly cleaned up if it was possible. 
                        //
                        // Now all we need to do is to Record the exception in the root task. 

                        root.HandleException(e);
                    }
 
                    // No specific action needed if the child could not be canceled
                    // because we attached it to the root task, which should therefore be receiving any exceptions from the child, 
                    // and root.wait will not return before this child finishes anyway. 

                } 
            };

            //
            // Now we execute as the root task 
            //
            taskReplicaDelegate(null); 
        } 

        ///  
        /// IThreadPoolWorkItem override, which is the entry function for this task when the TP scheduler decides to run it.
        ///
        /// 
        [SecurityCritical] 
        void IThreadPoolWorkItem.ExecuteWorkItem()
        { 
            ExecuteEntry(false); 
        }
 
        /// 
        /// The ThreadPool calls this if a ThreadAbortException is thrown while trying to execute this workitem.  This may occur
        /// before Task would otherwise be able to observe it.
        ///  
        [SecurityCritical]
        void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) 
        { 
            // If the task has marked itself as Completed, then it either a) already observed this exception (so we shouldn't handle it here)
            // or b) completed before the exception ocurred (in which case it shouldn't count against this Task). 
            if (!IsCompleted)
            {
                HandleException(tae);
                FinishThreadAbortedTask(true, false); 
            }
        } 
 
        /// 
        /// Outermost entry function to execute this task. Handles all aspects of executing a task on the caller thread. 
        /// Currently this is called by IThreadPoolWorkItem.ExecuteWorkItem(), and TaskManager.TryExecuteInline.
        ///
        /// 
        ///  Performs atomic updates to prevent double execution. Should only be set to true 
        /// in codepaths servicing user provided TaskSchedulers. The ConcRT or ThreadPool schedulers don't need this. 
        [SecuritySafeCritical] 
        internal bool ExecuteEntry(bool bPreventDoubleExecution) 
        {
            if (bPreventDoubleExecution || ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0) ) 
            {
                int previousState = 0;

                // Do atomic state transition from queued to invoked. If we observe a task that's already invoked, 
                // we will return false so that TaskScheduler.ExecuteTask can throw an exception back to the custom scheduler.
                // However we don't want this exception to be throw if the task was already canceled, because it's a 
                // legitimate scenario for custom schedulers to dequeue a task and mark it as canceled (example: throttling scheduler) 
                if (!AtomicStateUpdate(TASK_STATE_DELEGATE_INVOKED, TASK_STATE_DELEGATE_INVOKED, ref previousState)
                    && (previousState & TASK_STATE_CANCELED) == 0) 
                {
                    // This task has already been invoked.  Don't invoke it again.
                    return false;
                } 
            }
            else 
            { 
                // Remember that we started running the task delegate.
                m_stateFlags |= TASK_STATE_DELEGATE_INVOKED; 
            }

            if (!IsCancellationRequested && !IsCanceled)
            { 
                ExecuteWithThreadLocal(ref ThreadLocals.s_currentTask);
            } 
            else if (!IsCanceled) 
            {
                int prevState = Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_CANCELED); 
                if ((prevState & TASK_STATE_CANCELED) == 0)
                {
                    CancellationCleanupLogic();
                } 
            }
 
            return true; 
        }
 
        // A trick so we can refer to the TLS slot with a byref.
        [SecurityCritical]
        private void ExecuteWithThreadLocal(ref Task currentTaskSlot)
        { 
            // Remember the current task so we can restore it after running, and then
            Task previousTask = currentTaskSlot; 
 
#if !FEATURE_PAL    // PAL doesn't support  eventing
            // ETW event for Task Started 
            if (TplEtwProvider.Log.IsEnabled(EventLevel.Verbose, ((EventKeywords)(-1))))
            {
                // previousTask holds the actual "current task" we want to report in the event
                if (previousTask != null) 
                    TplEtwProvider.Log.TaskStarted(previousTask.m_taskScheduler.Id, previousTask.Id, this.Id);
                else 
                    TplEtwProvider.Log.TaskStarted(TaskScheduler.Current.Id, 0, this.Id); 
            }
#endif 

            try
            {
                // place the current task into TLS. 
                currentTaskSlot = this;
 
                ExecutionContext ec = m_capturedContext; 
                if (ec == null)
                { 
                    // No context, just run the task directly.
                    Execute();
                }
                else 
                {
                    if (IsSelfReplicatingRoot || IsChildReplica) 
                    { 
                        m_capturedContext = ec.CreateCopy();
                    } 

                    // Run the task.  We need a simple shim that converts the
                    // object back into a Task object, so that we can Execute it.
#if PFX_LEGACY_3_5 
                    ExecutionContext.Run(ec, s_ecCallback, this);
#else 
                    ExecutionContext.Run(ec, s_ecCallback, this, true); 
#endif
                } 

                Finish(true);
            }
            finally 
            {
                currentTaskSlot = previousTask; 
            } 

#if !FEATURE_PAL    // PAL doesn't support  eventing 
            // ETW event for Task Completed
            if (TplEtwProvider.Log.IsEnabled(EventLevel.Verbose, ((EventKeywords)(-1))))
            {
                // previousTask holds the actual "current task" we want to report in the event 
                if (previousTask != null)
                    TplEtwProvider.Log.TaskCompleted(previousTask.m_taskScheduler.Id, previousTask.Id, this.Id, IsFaulted); 
                else 
                    TplEtwProvider.Log.TaskCompleted(TaskScheduler.Current.Id, 0, this.Id, IsFaulted);
            } 
#endif
        }

        [SecurityCritical] 
        private static ContextCallback s_ecCallback;
 
        [SecurityCritical] 
        private static void ExecutionContextCallback(object obj)
        { 
            Task task = obj as Task;
            Contract.Assert(task != null, "expected a task object");

            task.Execute(); 

        } 
 

        ///  
        /// The actual code which invokes the body of the task. This can be overriden in derived types.
        /// 
        internal void InnerInvoke()
        { 
            Contract.Assert(m_action != null, "Null action in InnerInvoke()");
 
            Action funcA = m_action as Action; 
            if (funcA != null)
            { 
                funcA();
            }
            else
            { 
                Action funcB = m_action as Action;
                funcB(m_stateObject); 
            } 
        }
 
        /// 
        /// Alternate InnerInvoke prototype to be called from ExecuteSelfReplicating() so that
        /// the Parallel Debugger can discover the actual task being invoked.
        /// Details: Here, InnerInvoke is actually being called on the rootTask object while we are actually executing the 
        /// childTask. And the debugger needs to discover the childTask, so we pass that down as an argument.
        /// The NoOptimization and NoInlining flags ensure that the childTask pointer is retained, and that this 
        /// function appears on the callstack. 
        /// 
        ///  
        [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
        internal void InnerInvokeWithArg(Task childTask)
        {
            InnerInvoke(); 
        }
 
        ///  
        /// Performs whatever handling is necessary for an unhandled exception. Normally
        /// this just entails adding the exception to the holder object. 
        /// 
        /// The exception that went unhandled.
        private void HandleException(Exception unhandledException)
        { 
            Contract.Assert(unhandledException != null);
 
            OperationCanceledException exceptionAsOce = unhandledException as OperationCanceledException; 
            if (exceptionAsOce != null && IsCancellationRequested &&
                m_contingentProperties.m_cancellationToken == exceptionAsOce.CancellationToken) 
            {
                // All conditions are satisfied for us to go into canceled state in Finish().
                // Mark the acknowledgement, and return without adding the exception.
                // 
                // However any OCE from the task that doesn't match the tasks' own CT,
                // or that gets thrown without the CT being set will be treated as an ordinary exception and added to the aggreagate 
 
                SetCancellationAcknowledged();
            } 
            else
            {

                AddException(unhandledException); 
            }
        } 
 
        /// 
        /// Waits for the  to complete execution. 
        /// 
        /// 
        /// The  was canceled -or- an exception was thrown during
        /// the execution of the . 
        /// 
        ///  
        /// The  has been disposed. 
        /// 
        public void Wait() 
        {
#if DEBUG
            bool waitResult =
#endif 
            Wait(Timeout.Infinite, CancellationToken.None);
 
#if DEBUG 
            Contract.Assert(waitResult, "expected wait to succeed");
#endif 
        }

        /// 
        /// Waits for the  to complete execution. 
        /// 
        ///  
        /// A  that represents the number of milliseconds to wait, or a  that represents -1 milliseconds to wait indefinitely.
        ///  
        /// 
        /// true if the  completed execution within the allotted time; otherwise, false.
        /// 
        ///  
        /// The  was canceled -or- an exception was thrown during the execution of the . 
        ///  
        /// 
        ///  is a negative number other than -1 milliseconds, which represents an 
        /// infinite time-out -or- timeout is greater than
        /// .
        /// 
        ///  
        /// The  has been disposed.
        ///  
        public bool Wait(TimeSpan timeout) 
        {
            long totalMilliseconds = (long)timeout.TotalMilliseconds; 
            if (totalMilliseconds < -1 || totalMilliseconds > 0x7fffffff)
            {
                throw new ArgumentOutOfRangeException("timeout");
            } 

            return Wait((int)totalMilliseconds, CancellationToken.None); 
        } 

 
        /// 
        /// Waits for the  to complete execution.
        /// 
        ///  
        /// A  to observe while waiting for the task to complete.
        ///  
        ///  
        /// The  was canceled.
        ///  
        /// 
        /// The  was canceled -or- an exception was thrown during the execution of the .
        ///  
        /// 
        /// The  
        /// has been disposed. 
        /// 
        public void Wait(CancellationToken cancellationToken) 
        {
            Wait(Timeout.Infinite, cancellationToken);
        }
 

        ///  
        /// Waits for the  to complete execution. 
        /// 
        ///  
        /// The number of milliseconds to wait, or  (-1) to
        /// wait indefinitely.
        /// true if the  completed execution within the allotted time; otherwise,
        /// false. 
        /// 
        ///  
        ///  is a negative number other than -1, which represents an 
        /// infinite time-out.
        ///  
        /// 
        /// The  was canceled -or- an exception was thrown during the execution of the .
        ///  
        /// 
        /// The  
        /// has been disposed. 
        /// 
        public bool Wait(int millisecondsTimeout) 
        {
            return Wait(millisecondsTimeout, CancellationToken.None);
        }
 

        ///  
        /// Waits for the  to complete execution. 
        /// 
        ///  
        /// The number of milliseconds to wait, or  (-1) to
        /// wait indefinitely.
        /// 
        ///  
        /// A  to observe while waiting for the task to complete.
        ///  
        ///  
        /// true if the  completed execution within the allotted time; otherwise, false.
        ///  
        /// 
        /// The  was canceled -or- an exception was thrown during the execution of the .
        ///  
        /// 
        /// The  
        /// has been disposed. 
        /// 
        ///  
        ///  is a negative number other than -1, which represents an
        /// infinite time-out.
        /// 
        ///  
        /// The  was canceled.
        ///  
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) 
        {
            ThrowIfDisposed(); 

            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("millisecondsTimeout"); 
            }
 
            // Return immediately if we know that we've completed "clean" -- no exceptions, no cancellations 
            if (CompletedSuccessfully) return true;
 
            if (!InternalWait(millisecondsTimeout, cancellationToken))
                return false;

            // If an exception occurred, or the task was cancelled, throw an exception. 
            ThrowIfExceptional(true);
 
            Contract.Assert((m_stateFlags & TASK_STATE_FAULTED) == 0, "Task.Wait() completing when in Faulted state."); 

            return true; 
        }

        // Convenience method that wraps any scheduler exception in a TaskSchedulerException
        // and rethrows it. 
        private bool WrappedTryRunInline()
        { 
            if (m_taskScheduler == null) 
                return false;
 
            try
            {
                return m_taskScheduler.TryRunInline(this, true);
            } 
            catch (Exception e)
            { 
                // we 1) either received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown 
                //    2) or a a ThreadAbortException, which we need to skip here, because it would already have been handled in Task.Execute
                if (!(e is ThreadAbortException)) 
                {
                    TaskSchedulerException tse = new TaskSchedulerException(e);
                    throw tse;
                } 
                else
                { 
                    throw; 
                }
            } 
        }

        // This overload takes advantage of known values for current scheduler & statics.
        // It looks a LOT like the version above, but perf considerations prevented me 
        // from having the one above call this one.
        private bool WrappedTryRunInline(TaskScheduler currentScheduler, object currentSchedulerStatics) 
        { 
            if (m_taskScheduler == null)
                return false; 

            try
            {
                if (currentScheduler == m_taskScheduler) 
                {
                    return currentScheduler.TryRunInline(this, true, currentSchedulerStatics); 
                } 
                else
                { 
                    return m_taskScheduler.TryRunInline(this, true);
                }
            }
            catch (Exception e) 
            {
                // we 1) either received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown 
                //    2) or a a ThreadAbortException, which we need to skip here, because it would already have been handled in Task.Execute 
                if (!(e is ThreadAbortException))
                { 
                    TaskSchedulerException tse = new TaskSchedulerException(e);
                    throw tse;
                }
                else 
                {
                    throw; 
                } 
            }
        } 

        /// 
        /// The core wait function, which is only accesible internally. It's meant to be used in places in TPL code where
        /// the current context is known or cached. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        internal bool InternalWait(int millisecondsTimeout, CancellationToken cancellationToken) 
        {
#if !FEATURE_PAL    // PAL doesn't support  eventing 
            // ETW event for Task Wait Begin
            if (TplEtwProvider.Log.IsEnabled(EventLevel.Verbose, ((EventKeywords)(-1))))
            {
                Task currentTask = Task.InternalCurrent; 
                TplEtwProvider.Log.TaskWaitBegin((currentTask != null ? currentTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentTask != null ? currentTask.Id : 0),
                                                  this.Id); 
            } 
#endif
 
            bool returnValue = IsCompleted;

            // If the event hasn't already been set, we will wait.
            if (!returnValue) 
            {
                // 
                // we will attempt inline execution only if an infinite wait was requested 
                // Inline execution doesn't make sense for finite timeouts and if a cancellation token was specified
                // because we don't know how long the task delegate will take. 
                //
                TaskScheduler tm = m_taskScheduler;
                if (millisecondsTimeout == Timeout.Infinite && !cancellationToken.CanBeCanceled &&
                    WrappedTryRunInline() && IsCompleted) // TryRunInline doesn't guarantee completion, as there may be unfinished children. 
                {
                    returnValue = true; 
                } 
                else
                { 
                    returnValue = CompletedEvent.Wait(millisecondsTimeout, cancellationToken);
                }
            }
 
            Contract.Assert(IsCompleted || millisecondsTimeout != Timeout.Infinite);
 
#if !FEATURE_PAL    // PAL doesn't support  eventing 
            // ETW event for Task Wait End
            if (TplEtwProvider.Log.IsEnabled(EventLevel.Verbose, ((EventKeywords)(-1)))) 
            {
                Task currentTask = Task.InternalCurrent;
                TplEtwProvider.Log.TaskWaitEnd((currentTask != null ? currentTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentTask != null ? currentTask.Id : 0),
                                                  this.Id); 
            }
#endif 
 
            return returnValue;
        } 


        /// 
        /// Cancels the . 
        /// 
        ///  Indiactes whether we should only cancel non-invoked tasks. 
        /// For the default scheduler this option will only be serviced through TryDequeue. 
        /// For custom schedulers we also attempt an atomic state transition.
        /// true if the task was successfully canceled; otherwise, false. 
        /// The 
        /// has been disposed.
        [SecuritySafeCritical]
        internal bool InternalCancel(bool bCancelNonExecutingOnly) 
        {
            Contract.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) == 0, "Task.InternalCancel() did not expect promise-style task"); 
            ThrowIfDisposed(); 

            bool bPopSucceeded = false; 
            bool mustCleanup = false;

            TaskSchedulerException tse = null;
 
            // If started, and running in a task context, we can try to pop the chore.
            if ((m_stateFlags & TASK_STATE_STARTED) != 0) 
            { 
                TaskScheduler ts = m_taskScheduler;
 
                try
                {
                    bPopSucceeded = (ts != null) && ts.TryDequeue(this);
                } 
                catch (Exception e)
                { 
                    // TryDequeue threw. We don't know whether the task was properly dequeued or not. So we must let the rest of 
                    // the cancellation logic run its course (record the request, attempt atomic state transition and do cleanup where appropriate)
                    // Here we will only record a TaskSchedulerException, which will later be thrown at function exit. 

                    if (!(e is ThreadAbortException))
                    {
                        tse = new TaskSchedulerException(e); 
                    }
                } 
 
                bool bRequiresAtomicStartTransition = ( ts != null && ts.RequiresAtomicStartTransition) || ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0);
 
                if (!bPopSucceeded && bCancelNonExecutingOnly && bRequiresAtomicStartTransition)
                {
                    // The caller requested cancellation of non-invoked tasks only, and TryDequeue was one way of doing it...
                    // Since that seems to have failed, we should now try an atomic state transition (from non-invoked state to canceled) 
                    // An atomic transition here is only safe if we know we're on a custom task scheduler, which also forces a CAS on ExecuteEntry
 
                    // Even though this task can't have any children, we should be ready for handling any continuations that 
                    // may be attached to it (although currently
                    // So we need to remeber whether we actually did the flip, so we can do clean up (finish continuations etc) 
                    mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED, TASK_STATE_DELEGATE_INVOKED | TASK_STATE_CANCELED);


                    // PS: This is slightly different from the regular cancellation codepath 
                    // since we record the cancellation request *after* doing the state transition.
                    // However that shouldn't matter too much because the task was never invoked, thus can't have children 
                } 

            } 

            if (!bCancelNonExecutingOnly || bPopSucceeded || mustCleanup)
            {
                // Record the cancellation request. 
                RecordInternalCancellationRequest();
 
                // Determine whether we need to clean up 
                // This will be the case
                //     1) if we were able to pop, and we win the ---- to update task state to TASK_STATE_CANCELED 
                //     2) if the task seems to be yet unstarted, and we win the ---- to transition to
                //        TASK_STATE_CANCELED before anyone else can transition into _STARTED or _CANCELED or
                //        _RAN_TO_COMPLETION or _FAULTED
                // Note that we do not check for TASK_STATE_COMPLETION_RESERVED.  That only applies to promise-style 
                // tasks, and a promise-style task should not enter into this codepath.
                if (bPopSucceeded) 
                { 
                    // hitting this would mean something wrong with the AtomicStateUpdate above
                    Contract.Assert(!mustCleanup, "Possibly an invalid state transition call was made in InternalCancel()"); 

                    // Include TASK_STATE_DELEGATE_INVOKED in "illegal" bits to protect against the situation where
                    // TS.TryDequeue() returns true but the task is still left on the queue.
                    mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED, TASK_STATE_CANCELED | TASK_STATE_DELEGATE_INVOKED); 
                }
                else if (!mustCleanup && (m_stateFlags & TASK_STATE_STARTED) == 0) 
                { 
                    mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED,
                        TASK_STATE_CANCELED | TASK_STATE_STARTED | TASK_STATE_RAN_TO_COMPLETION | 
                        TASK_STATE_FAULTED | TASK_STATE_DELEGATE_INVOKED);
                }

                // do the cleanup (i.e. set completion event and finish continuations) 
                if (mustCleanup)
                { 
                    CancellationCleanupLogic(); 
                }
            } 

            if (tse != null)
                throw tse;
            else 
                return (mustCleanup);
        } 
 
        // Breaks out logic for recording a cancellation request
        internal void RecordInternalCancellationRequest() 
        {
            // Record the cancellation request.
            LazyInitializer.EnsureInitialized(ref m_contingentProperties, s_contingentPropertyCreator);
 
            m_contingentProperties.m_internalCancellationRequested = CANCELLATION_REQUESTED;
 
        } 

        // ASSUMES THAT A SUCCESSFUL CANCELLATION HAS JUST OCCURRED ON THIS TASK!!! 
        // And this method should be called at most once per task.
        internal void CancellationCleanupLogic()
        {
            Contract.Assert((m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_COMPLETION_RESERVED)) != 0, "Task.CancellationCleanupLogic(): Task not canceled or reserved."); 
            // I'd like to do this, but there is a small window for a race condition.  If someone calls Wait() between InternalCancel() and
            // here, that will set m_completionEvent, leading to a meaningless/harmless assertion. 
            //Contract.Assert((m_completionEvent == null) || !m_completionEvent.IsSet, "Task.CancellationCleanupLogic(): Completion event already set."); 

            // This may have been set already, but we need to make sure. 
            Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_CANCELED);

            // Fire completion event if it has been lazily initialized
            SetCompleted(); 

            // Notify parents, fire continuations, other cleanup. 
            FinishStageThree(); 
        }
 

        /// 
        /// Sets the task's cancellation acknowledged flag.
        ///  
        private void SetCancellationAcknowledged()
        { 
            Contract.Assert(this == Task.InternalCurrent, "SetCancellationAcknowledged() should only be called while this is still the current task"); 
            Contract.Assert(IsCancellationRequested, "SetCancellationAcknowledged() should not be called if the task's CT wasn't signaled");
 
            m_stateFlags |= TASK_STATE_CANCELLATIONACKNOWLEDGED;
        }

 
        //
        // Continuation passing functionality (aka ContinueWith) 
        // 

        ///  
        /// A structure to hold continuation information.
        /// 
        internal struct TaskContinuation
        { 
            internal object m_task; // The delegate OR unstarted continuation task.
            internal TaskScheduler m_taskScheduler; // The TaskScheduler with which to associate the continuation task. 
            internal TaskContinuationOptions m_options; // What kind of continuation. 

            ///  
            /// Constructs a new continuation structure.
            /// 
            /// The task to be activated.
            /// The continuation options. 
            /// The scheduler to use for the continuation.
            internal TaskContinuation(Task task, TaskScheduler scheduler, TaskContinuationOptions options) 
            { 
                Contract.Assert(task != null, "TaskContinuation ctor: task is null");
 
                m_task = task;
                m_taskScheduler = scheduler;
                m_options = options;
            } 

            internal TaskContinuation(Action action) 
            { 
                m_task = action;
                m_taskScheduler = null; 
                m_options = TaskContinuationOptions.None;
            }

            ///  
            /// Invokes the continuation for the target completion task.
            ///  
            /// The completed task. 
            /// Whether the continuation can be inlined.
            [SecuritySafeCritical] // Needed for QueueTask 
            internal void Run(Task completedTask, bool bCanInlineContinuationTask)
            {
                Contract.Assert(completedTask.IsCompleted, "ContinuationTask.Run(): completedTask not completed");
 
                Task task = m_task as Task;
                if (task != null) 
                { 
                    if (completedTask.ContinueWithIsRightKind(m_options))
                    { 
                        task.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 && (m_options & TaskContinuationOptions.ExecuteSynchronously) != 0)
                        { 
                            // Execute() won't set the TASK_STATE_STARTED flag, so we'll do it here. 
                            if (!task.MarkStarted())
                            { 
                                // task has been canceled.  Abort this continuation thread.
                                return;
                            }
 
                            try
                            { 
                                if (!m_taskScheduler.TryRunInline(task, false)) 
                                {
                                    m_taskScheduler.QueueTask(task); 
                                }
                            }
                            catch (Exception e)
                            { 
                                // Either TryRunInline() or QueueTask() threw an exception. Record the exception, marking the task as Faulted.
                                // However if it was a ThreadAbortException coming from TryRunInline we need to skip here, 
                                // because it would already have been handled in Task.Execute() 
                                if (!(e is ThreadAbortException &&
                                      (task.m_stateFlags & TASK_STATE_THREAD_WAS_ABORTED) != 0))    // this ensures TAEs from QueueTask will be wrapped in TSE 
                                {
                                    TaskSchedulerException tse = new TaskSchedulerException(e);
                                    task.AddException(tse);
                                    task.Finish(false); 
                                }
 
                                // Don't re-throw. 
                            }
                        } 
                        else
                        {
                            try
                            { 
                                task.ScheduleAndStart(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.
                            }
                        } 
                    }
                    else 
                    { 
                        // The final state of this task does not match the desired
                        // continuation activation criteria; cancel it to denote this. 
                        task.InternalCancel(false);
                    }
                }
                else 
                {
                    // Note for the future: ContinuationAction still run synchronously regardless of ThreadAbortException handling. 
                    // This is probably not too importnat right now, because the internal use of continuationActions only involve short actions. 
                    // However if we ever make these public, we need to turn them into tasks if the antecedent threw a ThreadAbortException.
                    Action action = m_task as Action; 
                    Contract.Assert(action != null, "TaskContinuation.Run(): Unknown m_task type.");
                    action(completedTask);
                }
            } 
        }
 
        ///  
        /// Runs all of the continuations, as appropriate.
        ///  
        private void FinishContinuations()
        {
            // Grab the list of continuations, and lock it to contend with concurrent adds.
            // At this point, IsCompleted == true, so those adding will either come before 
            // that and add a continuation under the lock (serializing before this), so we
            // will run it; or they will attempt to acquire the lock, get it, and then see the 
            // task is completed (serializing after this), and run it on their own. 
            List continuations = (m_contingentProperties == null) ? null : m_contingentProperties.m_continuations;
            if (continuations != null) 
            {
                lock (m_contingentProperties)
                {
                    // Ensure that all concurrent adds have completed. 
                }
 
                // skip synchronous execution of continuations if this tasks thread was aborted 
                bool bCanInlineContinuations = !(((m_stateFlags & TASK_STATE_THREAD_WAS_ABORTED) != 0) ||
                                                  (Thread.CurrentThread.ThreadState == ThreadState.AbortRequested)); 

                // Records earliest index of synchronous continuation.
                // A value of -1 means that no synchronous continuations were found.
                int firstSynchronousContinuation = -1; 

                // Fire the asynchronous continuations first ... 
                // Go back-to-front to make the "firstSynchronousContinuation" logic simpler. 
                for (int i = continuations.Count - 1; i >= 0; i--)
                { 
                    TaskContinuation tc = continuations[i];
                    // ContinuationActions, which execute synchronously, have a null scheduler
                    // Synchronous continuation tasks will have the ExecuteSynchronously option
                    if ((tc.m_taskScheduler != null) && ((tc.m_options & TaskContinuationOptions.ExecuteSynchronously) == 0)) 
                    {
                        tc.Run(this, bCanInlineContinuations); 
                    } 
                    else firstSynchronousContinuation = i;
                } 

                // ... and then fire the synchronous continuations (if there are any)
                if (firstSynchronousContinuation > -1)
                { 
                    for (int i = firstSynchronousContinuation; i < continuations.Count; i++)
                    { 
                        TaskContinuation tc = continuations[i]; 
                        // ContinuationActions, which execute synchronously, have a null scheduler
                        // Synchronous continuation tasks will have the ExecuteSynchronously option 
                        if ((tc.m_taskScheduler == null) || ((tc.m_options & TaskContinuationOptions.ExecuteSynchronously) != 0))
                            tc.Run(this, bCanInlineContinuations);
                    }
                } 

                // Don't keep references to "spent" continuations 
                m_contingentProperties.m_continuations = null; 
            }
        } 

        /// 
        /// Helper function to determine whether the current task is in the state desired by the
        /// continuation kind under evaluation. Three possibilities exist: the task failed with 
        /// an unhandled exception (OnFailed), the task was canceled before running (OnAborted),
        /// or the task completed successfully (OnCompletedSuccessfully).  Note that the last 
        /// one includes completing due to cancellation. 
        /// 
        /// The continuation options under evaluation. 
        /// True if the continuation should be run given the task's current state.
        internal bool ContinueWithIsRightKind(TaskContinuationOptions options)
        {
            Contract.Assert(IsCompleted); 

            if (IsFaulted) 
            { 
                return (options & TaskContinuationOptions.NotOnFaulted) == 0;
            } 
            else if (IsCanceled)
            {
                return (options & TaskContinuationOptions.NotOnCanceled) == 0;
            } 
            else
            { 
                return (options & TaskContinuationOptions.NotOnRanToCompletion) == 0; 
            }
        } 

        /// 
        /// 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. 
        /// 
        ///  
        /// 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  that will be assigned to the new continuation task. 
        /// 
        /// 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, just with a stack mark parameter. 
        private Task ContinueWith(Action continuationAction, TaskScheduler scheduler, 
            CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
        { 
            ThrowIfDisposed();

            // Throw on continuation with null action
            if (continuationAction == null) 
            {
                throw new ArgumentNullException("continuationAction"); 
            } 

            // Throw on continuation with null TaskScheduler 
            if (scheduler == null)
            {
                throw new ArgumentNullException("scheduler");
            } 

            TaskCreationOptions creationOptions; 
            InternalTaskOptions internalOptions; 
            CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
 
            Task thisTask = this;
            Task continuationTask = new Task(
                delegate(object obj) { continuationAction(thisTask); },
                null, 
                Task.InternalCurrent,
                cancellationToken, 
                creationOptions, 
                internalOptions,
                null, // leave taskScheduler 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 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 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(Func 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 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. 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(Func 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 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(Func 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 parameter.
        private Task ContinueWith(Func continuationFunction, TaskScheduler scheduler, 
            CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark) 
        {
            ThrowIfDisposed(); 

            // Throw on continuation with null function
            if (continuationFunction == null)
            { 
                throw new ArgumentNullException("continuationFunction");
            } 
 
            // Throw on continuation with null task scheduler
            if (scheduler == null) 
            {
                throw new ArgumentNullException("scheduler");
            }
 
            TaskCreationOptions creationOptions;
            InternalTaskOptions internalOptions; 
            CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions); 

            Task thisTask = this; 
            Task continuationTask = new Task(
                delegate() { return continuationFunction(thisTask); },
                Task.InternalCurrent,
                cancellationToken, 
                creationOptions,
                internalOptions, 
                null, // leave taskScheduler 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; 
        } 

        ///  
        /// Converts TaskContinuationOptions to TaskCreationOptions, and also does
        /// some validity checking along the way.
        /// 
        /// Incoming TaskContinuationOptions 
        /// Outgoing TaskCreationOptions
        /// Outgoing InternalTaskOptions 
        internal static void CreationOptionsFromContinuationOptions( 
            TaskContinuationOptions continuationOptions,
            out TaskCreationOptions creationOptions, 
            out InternalTaskOptions internalOptions)
        {
            // This is used a couple of times below
            TaskContinuationOptions NotOnAnything = 
                TaskContinuationOptions.NotOnCanceled |
                TaskContinuationOptions.NotOnFaulted | 
                TaskContinuationOptions.NotOnRanToCompletion; 

            TaskContinuationOptions creationOptionsMask = 
                TaskContinuationOptions.PreferFairness |
                TaskContinuationOptions.LongRunning |
                TaskContinuationOptions.AttachedToParent;
 

            // Check that LongRunning and ExecuteSynchronously are not specified together 
            TaskContinuationOptions illegalMask = TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.LongRunning; 
            if ((continuationOptions & illegalMask) == illegalMask)
            { 
                throw new ArgumentOutOfRangeException("continuationOptions", Environment.GetResourceString("Task_ContinueWith_ESandLR"));
            }

            // Check that no illegal options were specified 
            if ((continuationOptions &
                ~(creationOptionsMask | NotOnAnything | 
                  TaskContinuationOptions.ExecuteSynchronously)) != 0) 
            {
                throw new ArgumentOutOfRangeException("continuationOptions"); 
            }

            // Check that we didn't specify "not on anything"
            if ((continuationOptions & NotOnAnything) == NotOnAnything) 
            {
                throw new ArgumentOutOfRangeException("continuationOptions", Environment.GetResourceString("Task_ContinueWith_NotOnAnything")); 
            } 

            creationOptions = (TaskCreationOptions)(continuationOptions & creationOptionsMask); 
            internalOptions = InternalTaskOptions.ContinuationTask;
        }

 
        /// 
        /// Registers the continuation and possibly runs it (if the task is already finished). 
        ///  
        /// The continuation task itself.
        /// TaskScheduler with which to associate continuation task. 
        /// Restrictions on when the continuation becomes active.
        internal void ContinueWithCore(Task continuationTask, TaskScheduler scheduler, TaskContinuationOptions options)
        {
            Contract.Assert(continuationTask != null, "Task.ContinueWithCore(): null continuationTask"); 
            Contract.Assert((!continuationTask.IsCompleted) || continuationTask.CancellationToken.IsCancellationRequested,
                "Task.ContinueWithCore(): continuationTask is completed and its CT is not signaled"); 
 
            // It doesn't really do any harm to queue up an already-completed continuation, but it's
            // a little wasteful.  So we'll make an attempt at avoiding it (although the race condition 
            // here could still result in a completed continuation task being queued.)
            if (continuationTask.IsCompleted) return;

            TaskContinuation continuation = new TaskContinuation(continuationTask, scheduler, options); 

            // If the task has not finished, we will enqueue the continuation to fire when completed. 
            if (!IsCompleted) 
            {
                // If not created yet, we will atomically initialize the queue of actions. 
                LazyInitializer.EnsureInitialized(ref m_contingentProperties, s_contingentPropertyCreator);
                if (m_contingentProperties.m_continuations == null)
                {
                    Interlocked.CompareExchange(ref m_contingentProperties.m_continuations, new List(), null); 
                }
 
                // Now we must serialize access to the list itself. 
                lock (m_contingentProperties)
                { 
                    // We have to check IsCompleted again here, since the task may have
                    // finished before we got around to acquiring the lock on the actions.
                    // There is a race condition here, but it's OK.  If the thread that
                    // finishes the task notices a non-null actions queue it will try to 
                    // acquire a lock on it.  Thus it will have to wait for the current
                    // thread to exit the critical region we're currently in. 
                    if (!IsCompleted) 
                    {
                        m_contingentProperties.m_continuations.Add(continuation); 
                        return;
                    }
                }
            } 

            // If we fell through, the task has already completed.  We'll invoke the action inline. 
            // Only start the continuation if the right kind was established. 
            continuation.Run(this, true);
        } 

        // Adds a lightweight completion action to a task.  This is similar to a continuation
        // task except that it is stored as an action, and thus does not require the allocation/
        // execution resources of a continuation task. 
        //
        // Used internally by ContinueWhenAll() and ContinueWhenAny(). 
        internal void AddCompletionAction(Action action) 
        {
            if (!IsCompleted) 
            {
                LazyInitializer.EnsureInitialized(ref m_contingentProperties, s_contingentPropertyCreator);
                TaskContinuation tc = new TaskContinuation(action);
                if (m_contingentProperties.m_continuations == null) 
                {
                    Interlocked.CompareExchange(ref m_contingentProperties.m_continuations, new List(), null); 
                } 

                // Serialize access to the continuations list 
                lock (m_contingentProperties)
                {
                    // We have to check IsCompleted again here, since the task may have
                    // finished before we got around to acquiring the lock on the actions. 
                    // There is a race condition here, but it's OK.  If the thread that
                    // finishes the task notices a non-null actions queue it will try to 
                    // acquire a lock on it.  Thus it will have to wait for the current 
                    // thread to exit the critical region we're currently in.
                    if (!IsCompleted) 
                    {
                        m_contingentProperties.m_continuations.Add(tc);
                        return;
                    } 
                }
            } 
 
            // If we got this far, we've already completed
            action(this); 
        }


        // 
        // Wait methods
        // 
 
        /// 
        /// Waits for all of the provided  objects to complete execution. 
        /// 
        /// 
        /// An array of  instances on which to wait.
        ///  
        /// 
        /// The  argument is null. 
        ///  
        /// 
        /// The  argument contains a null element. 
        /// 
        /// 
        /// At least one of the  instances was canceled -or- an exception was thrown during
        /// the execution of at least one of the  instances. 
        /// 
        ///  
        /// The  has been disposed. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static void WaitAll(params Task[] tasks)
        {
#if DEBUG
            bool waitResult = 
#endif
            WaitAll(tasks, Timeout.Infinite); 
 
#if DEBUG
            Contract.Assert(waitResult, "expected wait to succeed"); 
#endif
        }

        ///  
        /// Waits for all of the provided  objects to complete execution.
        ///  
        ///  
        /// true if all of the  instances completed execution within the allotted time;
        /// otherwise, false. 
        /// 
        /// 
        /// An array of  instances on which to wait.
        ///  
        /// 
        /// A  that represents the number of milliseconds to wait, or a  that represents -1 milliseconds to wait indefinitely. 
        /// 
        ///  
        /// The  argument is null.
        /// 
        /// 
        /// The  argument contains a null element. 
        /// 
        ///  
        /// At least one of the  instances was canceled -or- an exception was thrown during 
        /// the execution of at least one of the  instances.
        ///  
        /// 
        ///  is a negative number other than -1 milliseconds, which represents an
        /// infinite time-out -or- timeout is greater than
        /// . 
        /// 
        ///  
        /// The  has been disposed. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static bool WaitAll(Task[] tasks, TimeSpan timeout)
        {
            long totalMilliseconds = (long)timeout.TotalMilliseconds;
            if (totalMilliseconds < -1 || totalMilliseconds > 0x7fffffff) 
            {
                throw new ArgumentOutOfRangeException("timeout"); 
            } 

            return WaitAll(tasks, (int)totalMilliseconds); 

        }

        ///  
        /// Waits for all of the provided  objects to complete execution.
        ///  
        ///  
        /// true if all of the  instances completed execution within the allotted time;
        /// otherwise, false. 
        /// 
        /// 
        /// The number of milliseconds to wait, or  (-1) to
        /// wait indefinitely. 
        /// An array of  instances on which to wait.
        ///  
        ///  
        /// The  argument is null.
        ///  
        /// 
        /// The  argument contains a null element.
        /// 
        ///  
        /// At least one of the  instances was canceled -or- an exception was thrown during
        /// the execution of at least one of the  instances. 
        ///  
        /// 
        /// The  has been disposed. 
        /// 
        /// 
        ///  is a negative number other than -1, which represents an
        /// infinite time-out. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static bool WaitAll(Task[] tasks, int millisecondsTimeout) 
        {
            return WaitAll(tasks, millisecondsTimeout, CancellationToken.None); 
        }

        /// 
        /// Waits for all of the provided  objects to complete execution. 
        /// 
        ///  
        /// true if all of the  instances completed execution within the allotted time; 
        /// otherwise, false.
        ///  
        /// 
        /// An array of  instances on which to wait.
        /// 
        ///  
        /// A  to observe while waiting for the tasks to complete.
        ///  
        ///  
        /// The  argument is null.
        ///  
        /// 
        /// The  argument contains a null element.
        /// 
        ///  
        /// At least one of the  instances was canceled -or- an exception was thrown during
        /// the execution of at least one of the  instances. 
        ///  
        /// 
        /// The  was canceled. 
        /// 
        /// 
        /// The  has been disposed.
        ///  
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
        public static void WaitAll(Task[] tasks, CancellationToken cancellationToken) 
        { 
            WaitAll(tasks, Timeout.Infinite, cancellationToken);
        } 

        /// 
        /// Waits for all of the provided  objects to complete execution.
        ///  
        /// 
        /// true if all of the  instances completed execution within the allotted time; 
        /// otherwise, false. 
        /// 
        ///  
        /// An array of  instances on which to wait.
        /// 
        /// 
        /// The number of milliseconds to wait, or  (-1) to 
        /// wait indefinitely.
        ///  
        ///  
        /// A  to observe while waiting for the tasks to complete.
        ///  
        /// 
        /// The  argument is null.
        /// 
        ///  
        /// The  argument contains a null element.
        ///  
        ///  
        /// At least one of the  instances was canceled -or- an exception was thrown during
        /// the execution of at least one of the  instances. 
        /// 
        /// 
        /// The  has been disposed.
        ///  
        /// 
        ///  is a negative number other than -1, which represents an 
        /// infinite time-out. 
        /// 
        ///  
        /// The  was canceled.
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
        public static bool WaitAll(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken) 
        {
            if (tasks == null) 
            { 
                throw new ArgumentNullException("tasks");
            } 
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("timeout");
            } 

#if DEBUG 
            Contract.Assert(tasks != null && millisecondsTimeout >= -1, "invalid arguments passed to WaitAll"); 
#endif
            cancellationToken.ThrowIfCancellationRequested(); // early check before we make any allocations 

            //
            // In this WaitAll() implementation we have 2 alternate code paths for a task to be handled:
            // CODEPATH1: skip an already completed task, CODEPATH2: actually wait on task's handle 
            // We make sure that the exception behavior of Task.Wait() is replicated the same for tasks handled in either of these codepaths
            // 
 
            List exceptions = null;
            List waitedOnTaskList = null; // tasks whose async handles we actually grabbed 

            bool returnValue = true;
            Task currentTask = Task.InternalCurrent;
            TaskScheduler currentTm = (currentTask == null) ? TaskScheduler.Default : currentTask.ExecutingTaskScheduler; 
            object currentTmStatics = currentTm.GetThreadStatics();
 
            // Collects incomplete tasks in "waitedOnTaskList" 
            for (int i = tasks.Length - 1; i >= 0; i--)
            { 
                Task task = tasks[i];

                if (task == null)
                { 
                    throw new ArgumentException(Environment.GetResourceString("Task_WaitMulti_NullTask"), "tasks");
                } 
 
                task.ThrowIfDisposed();
 
                bool taskIsCompleted = task.IsCompleted;
                if (!taskIsCompleted)
                {
                    // try inlining the task only if we have an infinite timeout and an empty cancellation token 
                    if (millisecondsTimeout != Timeout.Infinite || cancellationToken.CanBeCanceled)
                    { 
                        // We either didn't attempt inline execution because we had a non-infinite timeout or we had a cancellable token. 
                        // In all cases we need to do a full wait on the task (=> add its event into the list.)
                        if (waitedOnTaskList == null) 
                        {
                            waitedOnTaskList = new List(tasks.Length);
                        }
                        waitedOnTaskList.Add(task); 
                    }
                    else 
                    { 
                        // We are eligible for inlining.
                        taskIsCompleted = task.WrappedTryRunInline(currentTm, currentTmStatics) && 
                            task.IsCompleted; // A successful TryRunInline doesn't guarantee completion

                        if (!taskIsCompleted)
                        { 
                            // Inlining didn't work.
                            // Do a full wait on the task (=> add its event into the list.) 
                            if (waitedOnTaskList == null) 
                            {
                                waitedOnTaskList = new List(tasks.Length); 
                            }
                            waitedOnTaskList.Add(task);

                        } 
                    }
                } 
 
                if (taskIsCompleted)
                { 
                    // The task has finished. Make sure we aggregate its exceptions.
                    AddExceptionsForCompletedTask(ref exceptions, task);

                } 
            }
 
            if (waitedOnTaskList != null) 
            {
                Contract.Assert(waitedOnTaskList.Count > 0); 
                WaitHandle[] waitHandles = new WaitHandle[waitedOnTaskList.Count];
                for (int i = 0; i < waitHandles.Length; i++)
                {
                    waitHandles[i] = waitedOnTaskList[i].CompletedEvent.WaitHandle; 
                }
                returnValue = WaitAllSTAAnd64Aware(waitHandles, millisecondsTimeout, cancellationToken); 
 
                // If the wait didn't time out, ensure exceptions are propagated.
                if (returnValue) 
                {
                    for (int i = 0; i < waitedOnTaskList.Count; i++)
                    {
                        AddExceptionsForCompletedTask(ref exceptions, waitedOnTaskList[i]); 
                    }
                } 
 
                // We need to prevent the tasks array from being GC'ed until we come out of the wait.
                // This is necessary so that the Parallel Debugger can traverse it during the long wait and deduce waiter/waitee relationships 
                GC.KeepAlive(tasks);
            }

            // If one or more threw exceptions, aggregate them. 
            if (exceptions != null)
            { 
                throw new AggregateException(exceptions); 
            }
 
            return returnValue;
        }

        ///  
        /// Waits for a set of handles in a STA-aware way.  In other words, it will wait for each
        /// of the events individually if we're on a STA thread, because MsgWaitForMultipleObjectsEx 
        /// can't do a true wait-all due to its hidden message queue event. This is not atomic, 
        /// of course, but we only wait on one-way (MRE) events anyway so this is OK.
        ///  
        /// An array of wait handles to wait on.
        /// The timeout to use during waits.
        /// The cancellationToken that enables a wait to be canceled.
        /// True if all waits succeeded, false if a timeout occurred. 
        private static bool WaitAllSTAAnd64Aware(WaitHandle[] waitHandles, int millisecondsTimeout, CancellationToken cancellationToken)
        { 
            const int MAX_WAIT_HANDLES = 64; 

            if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA 
                || cancellationToken.CanBeCanceled)
            {
                // We're on an STA thread, so we can't use the real Win32 wait-all.
                // We instead walk the list, and wait on each individually.  Perf will 
                // be poor because we'll incur O(N) context switches as we wake up.
 
                // CancellationToken enabled waits will also choose this codepath regardless of apartment state. 
                // The ability to use WaitAny to probe for cancellation during one by one waits makes it easy to support CT without introducing racy code paths.
 
                WaitHandle[] cancelableWHPair = null; // to be used with WaitAny if we have a CancellationToken

                if (cancellationToken.CanBeCanceled)
                { 
                    cancelableWHPair = new WaitHandle[2]; // one for the actual wait handle, other for the cancellation event
                    cancelableWHPair[1] = cancellationToken.WaitHandle; 
                } 

                for (int i = 0; i < waitHandles.Length; i++) 
                {
                    long startTicks = (millisecondsTimeout == Timeout.Infinite) ? 0 : DateTime.UtcNow.Ticks;

                    if (cancellationToken.CanBeCanceled) 
                    {
                        // do a WaitAny on the WH of interest and the cancellation event. 
                        cancelableWHPair[0] = waitHandles[i]; 
                        int waitRetCode = WaitHandle.WaitAny(cancelableWHPair, millisecondsTimeout, false);
                        if (waitRetCode == WaitHandle.WaitTimeout) 
                            return false;

                        // we could have come out of the wait due to index 1 (i.e. cancellationToken.WaitHandle), check and throw
                        cancellationToken.ThrowIfCancellationRequested(); 

                        // the wait should have returned 0, otherwise we have a bug in CT or the code above 
                        Contract.Assert(waitRetCode == 0, "Unexpected waitcode from WaitAny with cancellation event"); 
                    }
                    else 
                    {

                        if (!waitHandles[i].WaitOne(millisecondsTimeout, false))
                            return false; 
                    }
 
 
                    // Adjust the timeout.
                    if (millisecondsTimeout != Timeout.Infinite) 
                    {
                        long elapsedMilliseconds = (DateTime.UtcNow.Ticks - startTicks) / TimeSpan.TicksPerMillisecond;
                        if (elapsedMilliseconds > int.MaxValue || elapsedMilliseconds > millisecondsTimeout)
                            return false; 
                        millisecondsTimeout -= (int)elapsedMilliseconds;
                    } 
                } 
            }
            else if (waitHandles.Length <= MAX_WAIT_HANDLES) 
            {
                // We aren't on an STA thread, and have fewer than the Win32 limit.
                // Just issue a true wait-all wait.
 
                Contract.Assert(!cancellationToken.CanBeCanceled);
 
                if (!WaitHandle.WaitAll(waitHandles, millisecondsTimeout, false)) 
                    return false;
            } 
            else
            {
                // Otherwise, we need to chunk the handles into groups of the Win32 limit.
 
                Contract.Assert(!cancellationToken.CanBeCanceled);
 
                int chunks = (waitHandles.Length + MAX_WAIT_HANDLES - 1) / MAX_WAIT_HANDLES; 
                WaitHandle[] waitHandlesChunk = new WaitHandle[MAX_WAIT_HANDLES];
                long startTicks = (millisecondsTimeout == Timeout.Infinite) ? 0 : DateTime.UtcNow.Ticks; 

                for (int i = 0; i < chunks; i++)
                {
                    if (i == chunks - 1 && (waitHandles.Length % MAX_WAIT_HANDLES) != 0) 
                    {
                        // We're on the last chunk, and it's not evenly sized.  We need to 
                        // allocate an array of WaitHandles that is perfectly sized.  This is 
                        // because the WaitAll API doesn't allow null entries.
                        waitHandlesChunk = new WaitHandle[waitHandles.Length % MAX_WAIT_HANDLES]; 
                    }

                    Array.Copy(waitHandles, i * MAX_WAIT_HANDLES, waitHandlesChunk, 0, waitHandlesChunk.Length);
 
                    if (!WaitHandle.WaitAll(waitHandlesChunk, millisecondsTimeout, false))
                        return false; 
 
                    // Adjust the timeout.
                    if (millisecondsTimeout != Timeout.Infinite) 
                    {
                        long elapsedMilliseconds = (DateTime.UtcNow.Ticks - startTicks) / TimeSpan.TicksPerMillisecond;
                        if (elapsedMilliseconds > int.MaxValue || elapsedMilliseconds > millisecondsTimeout)
                            return false; 
                        millisecondsTimeout -= (int)elapsedMilliseconds;
                    } 
                } 
            }
 
            return true;
        }

        ///  
        /// Internal WaitAll implementation which is meant to be used with small number of tasks,
        /// optimized for Parallel.Invoke and other structured primitives. 
        ///  
        internal static void FastWaitAll(Task[] tasks)
        { 
#if DEBUG
            Contract.Assert(tasks != null);
#endif
 
            List exceptions = null;
            TaskScheduler currentTm = TaskScheduler.Current; 
            object currentTmStatics = currentTm.GetThreadStatics(); 

            // Collects incomplete tasks in "waitedOnTaskList" and their cooperative events in "cooperativeEventList" 
            for (int i = tasks.Length - 1; i >= 0; i--)
            {
                if (!tasks[i].IsCompleted)
                { 
                    // Just attempting to inline here... result doesn't matter.
                    // We'll do a second pass to do actual wait on each task, and to aggregate their exceptions. 
                    // If the task is inlined here, it will register as IsCompleted in the second pass 
                    // and will just give us the exception.
 
                    tasks[i].WrappedTryRunInline(currentTm, currentTmStatics);
                }
            }
 
            // Wait on the tasks.
            for (int i = tasks.Length - 1; i >= 0; i--) 
            { 
                tasks[i].CompletedEvent.Wait(); // Just a boolean check if the task is already done.
                AddExceptionsForCompletedTask(ref exceptions, tasks[i]); 
            }

            // If one or more threw exceptions, aggregate them.
            if (exceptions != null) 
            {
                throw new AggregateException(exceptions); 
            } 
        }
 
        /// 
        /// This internal function is only meant to be called by WaitAll()
        /// If the completed task is canceled or it has other exceptions, here we will add those
        /// into the passed in exception list (which will be lazily initialized here). 
        /// 
        internal static void AddExceptionsForCompletedTask(ref List exceptions, Task t) 
        { 
            AggregateException ex = t.GetExceptions(true);
            if (ex != null) 
            {
                // make sure the task's exception observed status is set appropriately
                // it's possible that WaitAll was called by the parent of an attached child,
                // this will make sure it won't throw again in the implicit wait 
                t.UpdateExceptionObservedStatus();
 
                if (exceptions == null) 
                {
                    exceptions = new List(ex.InnerExceptions.Count); 
                }

                exceptions.AddRange(ex.InnerExceptions);
            } 
        }
 
 
        /// 
        /// Waits for any of the provided  objects to complete execution. 
        /// 
        /// 
        /// An array of  instances on which to wait.
        ///  
        /// The index of the completed task in the  array argument.
        ///  
        /// The  argument is null. 
        /// 
        ///  
        /// The  argument contains a null element.
        /// 
        /// 
        /// The  has been disposed. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static int WaitAny(params Task[] tasks) 
        {
            int waitResult = WaitAny(tasks, Timeout.Infinite); 
            Contract.Assert(tasks.Length == 0 || waitResult != -1, "expected wait to succeed");
            return waitResult;
        }
 
        /// 
        /// Waits for any of the provided  objects to complete execution. 
        ///  
        /// 
        /// An array of  instances on which to wait. 
        /// 
        /// 
        /// A  that represents the number of milliseconds to wait, or a  that represents -1 milliseconds to wait indefinitely. 
        /// 
        ///  
        /// The index of the completed task in the  array argument, or -1 if the 
        /// timeout occurred.
        ///  
        /// 
        /// The  argument is null.
        /// 
        ///  
        /// The  argument contains a null element.
        ///  
        ///  
        /// The  has been disposed.
        ///  
        /// 
        ///  is a negative number other than -1 milliseconds, which represents an
        /// infinite time-out -or- timeout is greater than
        /// . 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static int WaitAny(Task[] tasks, TimeSpan timeout) 
        {
            long totalMilliseconds = (long)timeout.TotalMilliseconds; 
            if (totalMilliseconds < -1 || totalMilliseconds > 0x7fffffff)
            {
                throw new ArgumentOutOfRangeException("timeout");
            } 

            return WaitAny(tasks, (int)totalMilliseconds); 
        } 

        ///  
        /// Waits for any of the provided  objects to complete execution.
        /// 
        /// 
        /// An array of  instances on which to wait. 
        /// 
        ///  
        /// A  to observe while waiting for a task to complete. 
        /// 
        ///  
        /// The index of the completed task in the  array argument.
        /// 
        /// 
        /// The  argument is null. 
        /// 
        ///  
        /// The  argument contains a null element. 
        /// 
        ///  
        /// The  has been disposed.
        /// 
        /// 
        /// The  was canceled. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static int WaitAny(Task[] tasks, CancellationToken cancellationToken) 
        {
            return WaitAny(tasks, Timeout.Infinite, cancellationToken); 
        }

        /// 
        /// Waits for any of the provided  objects to complete execution. 
        /// 
        ///  
        /// An array of  instances on which to wait. 
        /// 
        ///  
        /// The number of milliseconds to wait, or  (-1) to
        /// wait indefinitely.
        /// 
        ///  
        /// The index of the completed task in the  array argument, or -1 if the
        /// timeout occurred. 
        ///  
        /// 
        /// The  argument is null. 
        /// 
        /// 
        /// The  argument contains a null element.
        ///  
        /// 
        /// The  has been disposed. 
        ///  
        /// 
        ///  is a negative number other than -1, which represents an 
        /// infinite time-out.
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
        public static int WaitAny(Task[] tasks, int millisecondsTimeout) 
        {
            return WaitAny(tasks, millisecondsTimeout, CancellationToken.None); 
        } 

        ///  
        /// Waits for any of the provided  objects to complete execution.
        /// 
        /// 
        /// An array of  instances on which to wait. 
        /// 
        ///  
        /// The number of milliseconds to wait, or  (-1) to 
        /// wait indefinitely.
        ///  
        /// 
        /// A  to observe while waiting for a task to complete.
        /// 
        ///  
        /// The index of the completed task in the  array argument, or -1 if the
        /// timeout occurred. 
        ///  
        /// 
        /// The  argument is null. 
        /// 
        /// 
        /// The  argument contains a null element.
        ///  
        /// 
        /// The  has been disposed. 
        ///  
        /// 
        ///  is a negative number other than -1, which represents an 
        /// infinite time-out.
        /// 
        /// 
        /// The  was canceled. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static int WaitAny(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken) 
        {
            if (tasks == null) 
            {
                throw new ArgumentNullException("tasks");
            }
            if (millisecondsTimeout < -1) 
            {
                throw new ArgumentOutOfRangeException("millisecondsTimeout"); 
            } 

#if DEBUG 
            Contract.Assert(tasks != null && millisecondsTimeout >= -1, "invalid arguments passed to WaitAny");
#endif
            cancellationToken.ThrowIfCancellationRequested(); // early check before we make any allocations
 
            int signaledTaskIndex = -1;
 
            // Some logic to help us deal with > 63/64 tasks 

            // Count the number of spaces in a 64-element arrat that we can't take up with Task WaitHandles. 
            int numReservations = (cancellationToken.CanBeCanceled ? 1 : 0) +
                ((Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) ? 1 : 0);
            int threshold = 64 - numReservations; // this is the number of tasks that we can wait on w/o "overflow"
            int firstBucketCount = 0; // number of tasks to pass to WaitAny 
            int secondBucketCount = 0; // number of tasks to pass to ContinueWhenAny
            if (tasks.Length > threshold) 
            { 
                // we need to divide the tasks into primary and overflow groups
                firstBucketCount = threshold - 1; // need space for overflow task handle 
                secondBucketCount = tasks.Length - firstBucketCount;
            }
            else firstBucketCount = tasks.Length; // no need for overflow -- secondBucketCount remains at 0.
 
            // Fast path for situation where at least one task has already completed...
            for (int taskIndex = 0; taskIndex < tasks.Length; taskIndex++) 
            { 
                Task task = tasks[taskIndex];
 
                if (task == null)
                {
                    throw new ArgumentException(Environment.GetResourceString("Task_WaitMulti_NullTask"), "tasks");
                } 

                // functional specification of WaitAny requires an immediate throw if any of the tasks are disposed 
                // we will simply discard any other exceptions that have been accumulated so far 
                task.ThrowIfDisposed();
 
                if (task.IsCompleted)
                {
                    // one of the tasks is already completed, we'll record its index if we haven't encountered another completed task yet
                    if (signaledTaskIndex == -1) 
                    {
                        signaledTaskIndex = taskIndex; 
                    } 
                }
            } 

            // Return early if tasks array is valid and a task had already completed
            if (signaledTaskIndex != -1) return signaledTaskIndex;
 
            // Now that we're done with the fast path, allocate arrays for defensive copies.
            Task[] tasksLocalCopy1 = new Task[firstBucketCount]; //local copy needed in case 'tasks' is modified externally when we're in the 2nd loop 
            Task[] tasksLocalCopy2 = (secondBucketCount > 0) ? new Task[secondBucketCount] : null; // overflow array -- only allocate if necessary 

            // Due to potential ----s, we need to check for null/disposed/completed again 
            // as we build our defensive copy array(s).
            for (int taskIndex = 0; taskIndex < tasks.Length; taskIndex++)
            {
                Task task = tasks[taskIndex]; 

                if (task == null) 
                { 
                    throw new ArgumentException(Environment.GetResourceString("Task_WaitMulti_NullTask"), "tasks");
                } 

                // populate the local arrays
                if (taskIndex < firstBucketCount) tasksLocalCopy1[taskIndex] = task;
                else tasksLocalCopy2[taskIndex - firstBucketCount] = task; 

                // functional specification of WaitAny requires an immediate throw if any of the tasks are disposed 
                // we will simply discard any other exceptions that have been accumulated so far 
                task.ThrowIfDisposed();
 
                if (task.IsCompleted)
                {
                    // one of the tasks is already completed, we'll record its index if we haven't encountered another completed task yet
                    if (signaledTaskIndex == -1) 
                    {
                        signaledTaskIndex = taskIndex; 
                    } 
                }
            } 

            if (signaledTaskIndex == -1 && tasks.Length != 0)
            {
                // Calculate length of handle array. 
                int handleArrayLength = firstBucketCount +
                                        ((secondBucketCount > 0) ? 1 : 0) + // add one for overflow bucket 
                                        (cancellationToken.CanBeCanceled ? 1 : 0); // add one for "live" cancellation token 

                Contract.Assert(handleArrayLength <= 64, "Task.WaitAny(): handleArrayLength too long"); 

                Task continuation = null; // used for overflow tasks

                WaitHandle[] waitHandles = new WaitHandle[handleArrayLength]; 
                for (int i = 0; i < firstBucketCount; i++)
                { 
                    waitHandles[i] = tasksLocalCopy1[i].CompletedEvent.WaitHandle; 
                }
 
                if (secondBucketCount > 0)
                {
                    // Aggregate the overflow tasks into a ContinueWhenAny()
                    continuation = Task.Factory.ContinueWhenAny(tasksLocalCopy2, delegate(Task antecedent) 
                    {
                        // We don't get index info from ContinueWhenAny(), so we'll need to manually look up the index 
                        for (int i = 0; i < tasksLocalCopy2.Length; i++) 
                        {
                            if (antecedent == tasksLocalCopy2[i]) return i; 
                        }
                        return tasksLocalCopy2.Length; // this would indicate a problem
                    });
                    waitHandles[firstBucketCount] = continuation.CompletedEvent.WaitHandle; 
                }
 
                if (cancellationToken.CanBeCanceled) 
                {
                    // Add the CT at the end 
                    waitHandles[handleArrayLength - 1] = cancellationToken.WaitHandle;
                }

                int waitValue = WaitHandle.WaitAny(waitHandles, millisecondsTimeout, false); 

                cancellationToken.ThrowIfCancellationRequested(); 
 
                Contract.Assert(!cancellationToken.CanBeCanceled
                                || waitValue != handleArrayLength - 1); // this would mean a bug in CT.WH or the code above 

                if (waitValue != WaitHandle.WaitTimeout)
                {
                    // The final waitValue may need some further massaging 
                    if ((secondBucketCount > 0) && (waitValue == firstBucketCount))
                    { 
                        Contract.Assert(continuation.IsCompleted, "Task.WaitAny(): expected continuation to have completed."); 
                        Contract.Assert(continuation.Result < tasksLocalCopy2.Length, "Task.WaitAny(): internal accounting error.");
                        waitValue = firstBucketCount + continuation.Result; 
                    }
                    signaledTaskIndex = waitValue; // which may end up being WaitHandle.WaitTimeout
                }
            } 

            // We need to prevent the tasks array from being GC'ed until we come out of the wait. 
            // This is necessary so that the Parallel Debugger can traverse it during the long wait and deduce waiter/waitee relationships 
            GC.KeepAlive(tasks);
 
            return signaledTaskIndex;
        }

    } 

    // Proxy class for better debugging experience 
    internal class SystemThreadingTasks_TaskDebugView 
    {
        private Task m_task; 

        public SystemThreadingTasks_TaskDebugView(Task task)
        {
            m_task = task; 
        }
 
        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; } }
    } 

 
    // Special purpose derivation of Task that supports limited replication through 
    // overriding the ShouldReplicate() method.  This is used by the Parallel.For/ForEach
    // methods. 
    internal class ParallelForReplicatingTask : Task
    {
        // Member variables
        private int m_replicationDownCount; // downcounter to control replication 

        // 
        // Constructors 
        //
 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
        internal ParallelForReplicatingTask(
            ParallelOptions parallelOptions, Action action, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions)
            : base(action, null, Task.InternalCurrent, CancellationToken.None, creationOptions, internalOptions | InternalTaskOptions.SelfReplicating, null) 
        {
            // Compute the down count based on scheduler/DOP info in parallelOptions. 
            m_replicationDownCount = parallelOptions.EffectiveMaxConcurrencyLevel; 

            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            PossiblyCaptureContext(ref stackMark);
        }

 
        // Controls degree of replication.  If downcounter is initialized to -1, then
        // replication will be allowed to "run wild".  Otherwise, this method decrements 
        // the downcounter each time it is called, calling false when it is called with 
        // a zero downcounter.  This method returning false effectively ends the replication
        // of the associated ParallelForReplicatingTask. 
        internal override bool ShouldReplicate()
        {
            if (m_replicationDownCount == -1) return true; // "run wild"
 
            if (m_replicationDownCount > 0) // Decrement and return true if not called with 0 downcount
            { 
                m_replicationDownCount--; 
                return true;
            } 

            return false; // We're done replicating
        }
 
        internal override Task CreateReplicaTask(Action taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
                                            TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica) 
        { 
            return new ParallelForReplicaTask(taskReplicaDelegate, stateObject, parentTask, taskScheduler,
                                            creationOptionsForReplica, internalOptionsForReplica); 
        }


    } 

    internal class ParallelForReplicaTask : Task 
    { 
        internal object m_stateForNextReplica;  // some replicas may quit prematurely, in which case they will use this variable
        // to save state they want to be picked up by the next replica queued to the same thread 

        internal object m_stateFromPreviousReplica;  // some replicas may quit prematurely, in which case they will use this variable
        // to save state they want to be picked up by the next replica queued to the same thread
 
        internal Task m_handedOverChildReplica;  // some replicas may quit prematurely, in which case they will use this variable
        // to hand over the child replica they had queued to the next task that will replace them 
 
        internal ParallelForReplicaTask(Action taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
                                       TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica) : 
            base(taskReplicaDelegate, stateObject, parentTask, CancellationToken.None, creationOptionsForReplica, internalOptionsForReplica, taskScheduler)
        {
        }
 
        /// 
        /// In some cases a replica will want to quit prematurely (ie. before finishing a chunk of work it may have grabbed) 
        /// yet they will need the next replica to pick things up from where they left. This API is used to save such state. 
        ///
        /// Calling it is also the only way to record a premature exit. 
        /// 
        /// 
        internal void SaveStateForNextReplica(object stateForNextReplica)
        { 
            m_stateForNextReplica = stateForNextReplica;
        } 
 
        // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
        internal override Object SavedStateForNextReplica 
        {
            get { return m_stateForNextReplica; }

            set { m_stateForNextReplica = value; } 
        }
 
        // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica 
        internal override Object SavedStateFromPreviousReplica
        { 
            get { return m_stateFromPreviousReplica; }

            set { m_stateFromPreviousReplica = value; }
        } 

        // Allows internal deriving classes to support replicas that exit prematurely and want to hand over the child replica that they 
        // had queued, so that the replacement replica can work with that child task instead of queuing up yet another one 
        internal override Task HandedOverChildReplica
        { 
            get { return m_handedOverChildReplica; }

            set { m_handedOverChildReplica = value; }
        } 
    }
 
 
    /// 
    /// Specifies flags that control optional behavior for the creation and execution of tasks. 
    /// 
    [Flags]
    [Serializable]
    public enum TaskCreationOptions 
    {
        ///  
        /// Specifies that the default behavior should be used. 
        /// 
        None = 0x0, 

        /// 
        /// A hint to a TaskScheduler to schedule a
        /// task in as fair a manner as possible, meaning that tasks scheduled sooner will be more likely to 
        /// be run sooner, and tasks scheduled later will be more likely to be run later.
        ///  
        PreferFairness = 0x01, 

        ///  
        /// Specifies that a task will be a long-running, course-grained operation. It provides a hint to the
        /// TaskScheduler that oversubscription may be
        /// warranted.
        ///  
        LongRunning = 0x02,
 
        ///  
        /// Specifies that a task is attached to a parent in the task hierarchy.
        ///  
        AttachedToParent = 0x04,
    }

 
    /// 
    /// Task creation flags which are only used internally. 
    ///  
    [Flags]
    [Serializable] 
    internal enum InternalTaskOptions
    {
        ///  Specifies "No internal task options" 
        None, 

        /// Used to filter out internal vs. public task creation options. 
        InternalOptionsMask = 0x0000FF00, 

        ChildReplica = 0x0100, 
        ContinuationTask = 0x0200,
        PromiseTask = 0x0400,
        SelfReplicating = 0x0800,
 
        /// Specifies that the task will be queued by the runtime before handing it over to the user.
        /// This flag will be used to skip the cancellationtoken registration step, which is only meant for unstarted tasks. 
        QueuedByRuntime = 0x2000 
    }
 
    /// 
    /// Specifies flags that control optional behavior for the creation and execution of continuation tasks.
    /// 
    [Flags] 
    [Serializable]
    public enum TaskContinuationOptions 
    { 
        /// 
        /// Default = "Continue on any, no task options, run asynchronously" 
        /// Specifies that the default behavior should be used.  Continuations, by default, will
        /// be scheduled when the antecedent task completes, regardless of the task's final TaskStatus.
        ///  
        None = 0,
 
        // These are identical to their meanings and values in TaskCreationOptions 

        ///  
        /// A hint to a TaskScheduler to schedule a
        /// task in as fair a manner as possible, meaning that tasks scheduled sooner will be more likely to
        /// be run sooner, and tasks scheduled later will be more likely to be run later.
        ///  
        PreferFairness = 0x01,
 
        ///  
        /// Specifies that a task will be a long-running, course-grained operation.  It provides
        /// a hint to the TaskScheduler that 
        /// oversubscription may be warranted.
        /// 
        LongRunning = 0x02,
        ///  
        /// Specifies that a task is attached to a parent in the task hierarchy.
        ///  
        AttachedToParent = 0x04, 

        // These are specific to continuations 

        /// 
        /// Specifies that the continuation task should not be scheduled if its antecedent ran to completion.
        /// This option is not valid for multi-task continuations. 
        /// 
        NotOnRanToCompletion = 0x10000, 
        ///  
        /// Specifies that the continuation task should not be scheduled if its antecedent threw an unhandled
        /// exception. This option is not valid for multi-task continuations. 
        /// 
        NotOnFaulted = 0x20000,
        /// 
        /// Specifies that the continuation task should not be scheduled if its antecedent was canceled. This 
        /// option is not valid for multi-task continuations.
        ///  
        NotOnCanceled = 0x40000, 
        /// 
        /// Specifies that the continuation task should be scheduled only if its antecedent ran to 
        /// completion. This option is not valid for multi-task continuations.
        /// 
        OnlyOnRanToCompletion = NotOnFaulted | NotOnCanceled,
        ///  
        /// Specifies that the continuation task should be scheduled only if its antecedent threw an
        /// unhandled exception. This option is not valid for multi-task continuations. 
        ///  
        OnlyOnFaulted = NotOnRanToCompletion | NotOnCanceled,
        ///  
        /// Specifies that the continuation task should be scheduled only if its antecedent was canceled.
        /// This option is not valid for multi-task continuations.
        /// 
        OnlyOnCanceled = NotOnRanToCompletion | NotOnFaulted, 
        /// 
        /// Specifies that the continuation task should be executed synchronously. With this option 
        /// specified, the continuation will be run on the same thread that causes the antecedent task to 
        /// transition into its final state. If the antecedent is already complete when the continuation is
        /// created, the continuation will run on the thread creating the continuation.  Only very 
        /// short-running continuations should be executed synchronously.
        /// 
        ExecuteSynchronously = 0x80000
    } 

    ///  
    /// Internal helper class to keep track of stack depth and decide whether we should inline or not. 
    /// 
    internal class StackGuard 
    {
        // current thread's depth of nested inline task executions
        private int m_inliningDepth = 0;
 
        // For relatively small inlining depths we don't want to get into the business of stack probing etc.
        // This clearly leaves a window of opportunity for the user code to SO. However a piece of code 
        // that can SO in 20 inlines on a typical 1MB stack size probably needs to be revisited anyway. 
        private const int s_maxUncheckedInliningDepth = 20;
 
#if !FEATURE_PAL && !PFX_LEGACY_3_5

        private UInt64 m_lastKnownWatermark;
        private static int s_pageSize; 

        // We are conservative here. We assume that the platform needs a whole 64KB to 
        // respond to stack overflow. This means that for very small stacks (e.g. 128KB) 
        // we'll fail a lot of stack checks incorrectly.
        private const long STACK_RESERVED_SPACE = 4096 * 16; 

#endif  // !FEATURE_PAL && !PFX_LEGACY_3_5

        ///  
        /// This method needs to be called before attempting inline execution on the current thread.
        /// If false is returned, it means we are too close to the end of the stack and should give up inlining. 
        /// Each call to TryBeginInliningScope() that returns true must be matched with a 
        /// call to EndInliningScope() regardless of whether inlining actually took place.
        ///  
        [SecuritySafeCritical]
        internal bool TryBeginInliningScope()
        {
            // If we're still under the 'safe' limit we'll just skip the stack probe to save p/invoke calls 
            if (m_inliningDepth < s_maxUncheckedInliningDepth || CheckForSufficientStack())
            { 
                m_inliningDepth++; 
                return true;
            } 
            else
                return false;
        }
 
        /// 
        /// This needs to be called once for each previous successful TryBeginInliningScope() call after 
        /// inlining related logic runs. 
        /// 
        [SecuritySafeCritical] 
        internal void EndInliningScope()
        {
            m_inliningDepth--;
            Contract.Assert(m_inliningDepth >= 0, "Inlining depth count should never go negative."); 

            // do the right thing just in case... 
            if (m_inliningDepth < 0) m_inliningDepth = 0; 
        }
 
        [SecurityCritical]
        private unsafe bool CheckForSufficientStack()
        {
#if !FEATURE_PAL && !PFX_LEGACY_3_5 
            // see if we already have the system page size info recorded
            if (s_pageSize == 0) 
            { 
                // If not we need to query it from GetSystemInfo()
                // Note that this happens only once for the process lifetime 
                Win32Native.SYSTEM_INFO sysInfo = new Win32Native.SYSTEM_INFO();
                Win32Native.GetSystemInfo(ref sysInfo);

                s_pageSize = sysInfo.dwPageSize; 
            }
 
            Win32Native.MEMORY_BASIC_INFORMATION stackInfo = new Win32Native.MEMORY_BASIC_INFORMATION(); 

            // We subtract one page for our request. VirtualQuery rounds UP to the next page. 
            // Unfortunately, the stack grows down. If we're on the first page (last page in the
            // VirtualAlloc), we'll be moved to the next page, which is off the stack!

            UIntPtr currentAddr = new UIntPtr(&stackInfo - s_pageSize); 
            UInt64 current64 = currentAddr.ToUInt64();
 
            // Check whether we previously recorded a deeper stack than where we currently are, 
            // If so we don't need to do the P/Invoke to VirtualQuery
            if (m_lastKnownWatermark != 0 && current64 > m_lastKnownWatermark) 
                return true;

            // Actual stack probe. P/Invoke to query for the current stack allocation information.
            Win32Native.VirtualQuery(currentAddr.ToPointer(), ref stackInfo, new IntPtr(sizeof(Win32Native.MEMORY_BASIC_INFORMATION))); 

            // If the current address minus the base (remember: the stack grows downward in the 
            // address space) is greater than the number of bytes requested plus the reserved 
            // space at the end, the request has succeeded.
 
            if ((current64 - ((UIntPtr)stackInfo.AllocationBase).ToUInt64()) > STACK_RESERVED_SPACE)
            {
                m_lastKnownWatermark = current64;
                return true; 
            }
 
            return false; 

#else // !FEATURE_PAL && !PFX_LEGACY_3_5 

            // if we're being compiled with FEATURE_PAL or PFX_LEGACY_3_5 we simply allow unchecked inlining.
            return true;
#endif 
        }
    } 
 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// 
// Task.cs 
//
// [....] 
//
// A schedulable unit of work.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices; 
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Threading; 
using System.Diagnostics;
using System.Diagnostics.Contracts; 
using System.Diagnostics.Eventing; 
using Microsoft.Win32;
 
// Disable the "reference to volatile field not treated as volatile" error.
#pragma warning disable 0420

namespace System.Threading.Tasks 
{
    ///  
    /// Represents the current stage in the lifecycle of a . 
    /// 
    public enum TaskStatus 
    {
        /// 
        /// The task has been initialized but has not yet been scheduled.
        ///  
        Created,
        ///  
        /// The task is waiting to be activated and scheduled internally by the .NET Framework infrastructure. 
        /// 
        WaitingForActivation, 
        /// 
        /// The task has been scheduled for execution but has not yet begun executing.
        /// 
        WaitingToRun, 
        /// 
        /// The task is running but has not yet completed. 
        ///  
        Running,
        // ///  
        // /// The task is currently blocked in a wait state.
        // /// 
        // Blocked,
        ///  
        /// The task has finished executing and is implicitly waiting for
        /// attached child tasks to complete. 
        ///  
        WaitingForChildrenToComplete,
        ///  
        /// The task completed execution successfully.
        /// 
        RanToCompletion,
        ///  
        /// The task acknowledged cancellation by throwing an OperationCanceledException with its own CancellationToken
        /// while the token was in signaled state, or the task's CancellationToken was already signaled before the 
        /// task started executing. 
        /// 
        Canceled, 
        /// 
        /// The task completed due to an unhandled exception.
        /// 
        Faulted 
    }
 
 
    /// 
    /// Represents an asynchronous operation. 
    /// 
    /// 
    /// 
    ///  instances may be created in a variety of ways. The most common approach is by 
    /// using the Task type's  property to retrieve a  instance that can be used to create tasks for several 
    /// purposes. For example, to create a  that runs an action, the factory's StartNew 
    /// method may be used:
    ///  
    /// // C#
    /// var t = Task.Factory.StartNew(() => DoAction());
    ///
    /// ' Visual Basic 
    /// Dim t = Task.Factory.StartNew(Function() DoAction())
    ///  
    ///  
    /// 
    /// The  class also provides constructors that initialize the Task but that do not 
    /// schedule it for execution. For performance reasons, TaskFactory's 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 
    /// method may then be used to schedule the task for execution at a later time. 
    /// 
    ///  
    /// All members of , except for , are thread-safe 
    /// and may be used from multiple threads concurrently.
    ///  
    /// 
    /// For operations that return values, the  class
    /// should be used.
    ///  
    /// 
    /// For developers implementing custom debuggers, several internal and private members of Task may be 
    /// useful (these may change from release to release). The Int32 m_taskId field serves as the backing 
    /// store for the  property, however accessing this field directly from a debugger may be
    /// more efficient than accessing the same value through the property's getter method (the 
    /// s_taskIdCounter Int32 counter is used to retrieve the next available ID for a Task). Similarly, the
    /// Int32 m_stateFlags field stores information about the current lifecycle stage of the Task,
    /// information also accessible through the  property. The m_action System.Object
    /// field stores a reference to the Task's delegate, and the m_stateObject System.Object field stores the 
    /// async state passed to the Task by the developer. Finally, for debuggers that parse stack frames, the
    /// InternalWait method serves a potential marker for when a Task is entering a wait operation. 
    ///  
    /// 
    [HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)] 
    [DebuggerTypeProxy(typeof(SystemThreadingTasks_TaskDebugView))]
    [DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}")]
    public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable
    { 

        // Accessing ThreadStatic variables on classes with class constructors is much slower than if the class 
        // has no class constructor.  So we declasre s_currentTask inside a nested class with no constructor. 
        // Do not put any static variables with explicit initialization in this class, as it will regress performance.
        private static class ThreadLocals 
        {
            [ThreadStatic]
            internal static Task s_currentTask;  // The currently executing task.
 
            [ThreadStatic]
            internal static StackGuard s_stackGuard;  // The stack guard object for this thread 
        } 

        internal static int s_taskIdCounter; //static counter used to generate unique task IDs 
        private static TaskFactory s_factory = new TaskFactory();

        private int m_taskId; // this task's unique ID. initialized only if it is ever requested
 
        internal object m_action;    // The body of the task.  Might be Action, Action or Action.
        // If m_action is set to null it will indicate that we operate in the 
        // "externally triggered completion" mode, which is exclusively meant 
        // for the signalling Task (aka. promise). In this mode,
        // we don't call InnerInvoke() in response to a Wait(), but simply wait on 
        // the completion event which will be set when the Future class calls Finish().
        // But the event would now be signalled if Cancel() is called

 
        internal object m_stateObject; // A state object that can be optionally supplied, passed to action.
        internal TaskScheduler m_taskScheduler; // The task scheduler this task runs under. @ 
 
        internal readonly Task m_parent; // A task's parent, or null if parent-less.
        internal ExecutionContext m_capturedContext; // The context to run the task within, if any. 

        internal volatile int m_stateFlags;

        // State constants for m_stateFlags; 
        // The bits of m_stateFlags are allocated as follows:
        //   0x40000000 - TaskBase state flag 
        //   0x3FFF0000 - Task state flags 
        //   0x0000FF00 - internal TaskCreationOptions flags
        //   0x000000FF - publicly exposed TaskCreationOptions flags 
        //
        // See TaskCreationOptions for bit values associated with TaskCreationOptions
        //
        private const int OptionsMask = 0xFFFF; // signifies the Options portion of m_stateFlags 
        internal const int TASK_STATE_STARTED = 0x10000;
        internal const int TASK_STATE_DELEGATE_INVOKED = 0x20000; 
        internal const int TASK_STATE_DISPOSED = 0x40000; 
        internal const int TASK_STATE_EXCEPTIONOBSERVEDBYPARENT = 0x80000;
        internal const int TASK_STATE_CANCELLATIONACKNOWLEDGED = 0x100000; 
        internal const int TASK_STATE_FAULTED = 0x200000;
        internal const int TASK_STATE_CANCELED = 0x400000;
        internal const int TASK_STATE_WAITING_ON_CHILDREN = 0x800000;
        internal const int TASK_STATE_RAN_TO_COMPLETION = 0x1000000; 
        internal const int TASK_STATE_WAITINGFORACTIVATION = 0x2000000;
        internal const int TASK_STATE_COMPLETION_RESERVED = 0x4000000; 
        internal const int TASK_STATE_THREAD_WAS_ABORTED = 0x8000000; 

        // Values for ContingentProperties.m_internalCancellationRequested. 
        internal static int CANCELLATION_REQUESTED = 0x1;

        private volatile ManualResetEventSlim m_completionEvent; // Lazily created if waiting is required.
 
        // We moved a number of Task properties into this class.  The idea is that in most cases, these properties never
        // need to be accessed during the life cycle of a Task, so we don't want to instantiate them every time.  Once 
        // one of these properties needs to be written, we will instantiate a ContingentProperties object and set 
        // the appropriate property.
        internal class ContingentProperties 
        {
            public volatile int m_internalCancellationRequested; // We keep canceled in its own field because threads legally ---- to set it.

            internal volatile int m_completionCountdown = 1; // # of active children + 1 (for this task itself). 
            // Used for ensuring all children are done before this task can complete
            // The extra count helps prevent the ---- for executing the final state transition 
            // (i.e. whether the last child or this task itself should call FinishStageTwo()) 

            public volatile TaskExceptionHolder m_exceptionsHolder; // Tracks exceptions, if any have occurred 

            public volatile List m_exceptionalChildren;       // A list of child tasks that threw an exception (TCEs don't count),
            // but haven't yet been waited on by the parent, lazily initialized.
 
            public volatile List m_continuations; // A list of tasks or actions to be started upon completion, lazily initialized.
 
            public CancellationToken m_cancellationToken; 
            public Shared m_cancellationRegistration;
        } 

        // This field will only be instantiated to some non-null value if any ContingentProperties need to be set.
        internal volatile ContingentProperties m_contingentProperties;
 
        /// 
        /// A type initializer that runs with the appropriate permissions. 
        ///  
        [SecuritySafeCritical]
        static Task() 
        {
            s_ecCallback = new ContextCallback(ExecutionContextCallback);
        }
 
        // Special internal constructor to create an already-completed task.
        // if canceled==true, create a Canceled task, or else create a RanToCompletion task. 
        internal Task(bool canceled, TaskCreationOptions creationOptions) 
        {
            int optionFlags = (int)creationOptions; 
            if (canceled) m_stateFlags = TASK_STATE_CANCELED | TASK_STATE_CANCELLATIONACKNOWLEDGED | optionFlags;
            else m_stateFlags = TASK_STATE_RAN_TO_COMPLETION | optionFlags;
        }
 
        // Special internal constructor to create an already-Faulted task.
        // Break this out when we need it. 
        // 
        //internal Task(Exception exception, bool attached)
        //{ 
        //    Task m_parent = attached ? Task.InternalCurrent : null;
        //
        //    if(m_parent != null) m_parent.AddNewChild();
        // 
        //    m_contingentProperties = new ContingentProperties();
        //    m_contingentProperties.m_exceptionsHolder = new TaskExceptionHolder(this); 
        //    m_contingentProperties.m_exceptionsHolder.Add(exception); 
        //    m_stateFlags = TASK_STATE_FAULTED;
        // 
        //    if (m_parent != null) m_parent.ProcessChildCompletion(this);
        //}

 

        // Special constructor for use with promise-style tasks. 
        // Added promiseStyle parameter as an aid to the compiler to distinguish between (state,TCO) and 
        // (action,TCO).  It should always be true.
        internal Task(object state, CancellationToken cancelationToken, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, bool promiseStyle) 
        {
            Contract.Assert(promiseStyle, "Promise CTOR: promiseStyle was false");

            // Check the creationOptions. We only allow the attached/detached option to be specified for promise tasks. 
            if ((creationOptions & ~(TaskCreationOptions.AttachedToParent)) != 0)
            { 
                throw new ArgumentOutOfRangeException("creationOptions"); 
            }
 
            if ((internalOptions & ~(InternalTaskOptions.PromiseTask)) != 0)
            {
                throw new ArgumentOutOfRangeException("internalOptions", Environment.GetResourceString("Task_PromiseCtor_IllegalInternalOptions"));
            } 

            // m_parent is readonly, and so must be set in the constructor. 
            // Only set a parent if AttachedToParent is specified. 
            if ((creationOptions & TaskCreationOptions.AttachedToParent) != 0)
                m_parent = Task.InternalCurrent; 

            TaskConstructorCore(null, state, cancelationToken, creationOptions, internalOptions, TaskScheduler.Current);
        }
 
        /// 
        /// Initializes a new  with the specified action. 
        ///  
        /// The delegate that represents the code to execute in the Task.
        /// The  argument is null. 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
        public Task(Action action)
            : this((object)action, null, Task.InternalCurrent, CancellationToken.None, TaskCreationOptions.None, InternalTaskOptions.None, null)
        { 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PossiblyCaptureContext(ref stackMark); 
        } 

        ///  
        /// Initializes a new  with the specified action and CancellationToken.
        /// 
        /// The delegate that represents the code to execute in the Task.
        /// The CancellationToken 
        /// that will 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(Action action, CancellationToken cancellationToken)
            : this((object)action, null, Task.InternalCurrent, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
        { 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PossiblyCaptureContext(ref stackMark); 
        } 

        ///  
        /// Initializes a new  with the specified action and creation options.
        /// 
        /// The delegate that represents the code to execute in the task.
        ///  
        /// 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(Action action, TaskCreationOptions creationOptions) 
            : this((object)action, null, Task.InternalCurrent, CancellationToken.None, creationOptions, InternalTaskOptions.None, null)
        { 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PossiblyCaptureContext(ref stackMark);
        }
 
        /// 
        /// Initializes a new  with the specified action and creation options. 
        ///  
        /// The delegate that represents the code to execute in the task.
        /// 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(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions) 
            : this((object)action, null, Task.InternalCurrent, cancellationToken, creationOptions, InternalTaskOptions.None, null)
        { 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PossiblyCaptureContext(ref stackMark);
        }
 

        ///  
        /// Initializes a new  with the specified action and state. 
        /// 
        /// The delegate that represents the code to execute in the task. 
        /// 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(Action action, object state) 
            : this((object)action, 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, snd options.
        ///  
        /// The delegate that represents the code to execute in the task. 
        /// An object representing data to be used by the action.
        /// The  that will 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(Action action, object state, CancellationToken cancellationToken)
            : this((object)action, state, Task.InternalCurrent, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null) 
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PossiblyCaptureContext(ref stackMark);
        } 

        ///  
        /// Initializes a new  with the specified action, state, snd options. 
        /// 
        /// The delegate that represents the code to execute in the task. 
        /// An object representing data to be used by the action.
        /// 
        /// 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(Action action, object state, TaskCreationOptions creationOptions)
            : this((object)action, state, Task.InternalCurrent, CancellationToken.None, creationOptions, InternalTaskOptions.None, null) 
        { 
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            PossiblyCaptureContext(ref stackMark); 
        }

        /// 
        /// Initializes a new  with the specified action, state, snd options. 
        /// 
        /// The delegate that represents the code to execute in the task. 
        /// An object representing data to be used by the action. 
        /// 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(Action action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) 
            : this((object)action, state, Task.InternalCurrent, cancellationToken, creationOptions, InternalTaskOptions.None, null) 
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            PossiblyCaptureContext(ref stackMark);
        }

 
        // For Task.ContinueWith() and Future.ContinueWith()
        internal Task(Action action, object state, Task parent, CancellationToken cancellationToken, 
            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark) 
            : this((object)action, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
        { 
            PossiblyCaptureContext(ref stackMark);
        }

        ///  
        /// An internal constructor used by the factory methods on task and its descendent(s).
        /// This variant does not capture the ExecutionContext; it is up to the caller to do that. 
        ///  
        /// An action to execute.
        /// Optional state to pass to the action. 
        /// Parent of Task.
        /// A CancellationToken for the task.
        /// A task scheduler under which the task will run.
        /// Options to control its execution. 
        /// Internal options to control its execution
        internal Task(object action, object state, Task parent, CancellationToken cancellationToken, 
            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) 
        {
            if (action == null) 
            {
                throw new ArgumentNullException("action");
            }
 
            Contract.Assert(action is Action || action is Action);
 
            // This is readonly, and so must be set in the constructor 
            // Keep a link to your parent if: (A) You are attached, or (B) you are self-replicating.
            // 
            if (((creationOptions & TaskCreationOptions.AttachedToParent) != 0) ||
                ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
                )
            { 
                m_parent = parent;
            } 
 
            TaskConstructorCore(action, state, cancellationToken, creationOptions, internalOptions, scheduler);
        } 

        /// 
        /// Common logic used by the following internal ctors:
        ///     Task() 
        ///     Task(object action, object state, Task parent, TaskCreationOptions options, TaskScheduler taskScheduler)
        /// 
        /// ASSUMES THAT m_creatingTask IS ALREADY SET. 
        ///
        ///  
        /// Action for task to execute.
        /// Object to which to pass to action (may be null)
        /// Task scheduler on which to run thread (only used by continuation tasks).
        /// A CancellationToken for the Task. 
        /// Options to customize behavior of Task.
        /// Internal options to customize behavior of Task. 
        internal void TaskConstructorCore(object action, object state, CancellationToken cancellationToken, 
            TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
        { 
            m_action = action;
            m_stateObject = state;
            m_taskScheduler = scheduler;
 
            // Check for validity of options
            if ((creationOptions & 
                    ~(TaskCreationOptions.AttachedToParent | 
                      TaskCreationOptions.LongRunning |
                      TaskCreationOptions.PreferFairness)) != 0) 
            {
                throw new ArgumentOutOfRangeException("creationOptions");
            }
 
            if ((internalOptions &
                    ~(InternalTaskOptions.SelfReplicating | 
                      InternalTaskOptions.ChildReplica | 
                      InternalTaskOptions.PromiseTask |
                      InternalTaskOptions.ContinuationTask | 
                      InternalTaskOptions.QueuedByRuntime)) != 0)
            {
                throw new ArgumentOutOfRangeException("internalOptions", Environment.GetResourceString("Task_ctor_IllegalInternalOptions"));
            } 

 
            // Throw exception if the user specifies both LongRunning and SelfReplicating 
            if (((creationOptions & TaskCreationOptions.LongRunning) != 0) &&
                ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)) 
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_ctor_LRandSR"));
            }
 
            // Assign options to m_stateAndOptionsFlag.
            Contract.Assert(m_stateFlags == 0, "TaskConstructorCore: non-zero m_stateFlags"); 
            Contract.Assert((((int)creationOptions) | OptionsMask) == OptionsMask, "TaskConstructorCore: options take too many bits"); 
            m_stateFlags = (int)creationOptions | (int)internalOptions;
 
            // For continuation tasks or TaskCompletionSource.Tasks, begin life in WaitingForActivation state
            // rather than Created state.
            if ((m_action == null) ||
                ((internalOptions & InternalTaskOptions.ContinuationTask) != 0)) 
            {
                m_stateFlags |= TASK_STATE_WAITINGFORACTIVATION; 
            } 

            // Now is the time to add the new task to the children list 
            // of the creating task if the options call for it.
            // We can safely call the creator task's AddNewChild() method to register it,
            // because at this point we are already on its thread of execution.
 
            if (m_parent != null && (creationOptions & TaskCreationOptions.AttachedToParent) != 0)
            { 
                m_parent.AddNewChild(); 
            }
 
            // if we have a non-null cancellationToken, allocate the contingent properties to save it
            // we need to do this as the very last thing in the construction path, because the CT registration could modify m_stateFlags
            if (cancellationToken.CanBeCanceled)
            { 
                Contract.Assert((internalOptions & (InternalTaskOptions.ChildReplica | InternalTaskOptions.SelfReplicating)) == 0,
                    "TaskConstructorCore: Did not expect to see cancellable token for replica/replicating task."); 
                LazyInitializer.EnsureInitialized(ref m_contingentProperties, s_contingentPropertyCreator); 
                m_contingentProperties.m_cancellationToken = cancellationToken;
 
                try
                {
                    cancellationToken.ThrowIfSourceDisposed();
 
                    // If an unstarted task has a valid CancellationToken that gets signalled while the task is still not queued
                    // we need to proactively cancel it, because it may never execute to transition itself. 
                    // The only way to accomplish this is to register a callback on the CT. 
                    // We exclude Promise tasks from this, because TasckCompletionSource needs to fully control the inner tasks's lifetime (i.e. not allow external cancellations)
                    if ((internalOptions & 
                        (InternalTaskOptions.QueuedByRuntime | InternalTaskOptions.PromiseTask)) == 0)
                    {
                        CancellationTokenRegistration ctr = cancellationToken.InternalRegisterWithoutEC(s_taskCancelCallback, this);
                        m_contingentProperties.m_cancellationRegistration = new Shared(ctr); 
                    }
                } 
                catch 
                {
                    // If we have an exception related to our CancellationToken, then we need to subtract ourselves 
                    // from our parent before throwing it.
                    if ((m_parent != null) && ((creationOptions & TaskCreationOptions.AttachedToParent) != 0))
                        m_parent.DisregardChild();
                    throw; 
                }
            } 
        } 

        ///  
        /// Checks if we registered a CT callback during construction, and deregisters it.
        /// This should be called when we know the registration isn't useful anymore. Specifically from Finish() if the task has completed
        /// successfully or with an exception.
        ///  
        internal void DeregisterCancellationCallback()
        { 
            if (m_contingentProperties != null && 
                m_contingentProperties.m_cancellationRegistration != null)
            { 
                // Harden against ODEs thrown from disposing of the CTR.
                // Since the task has already been put into a final state by the time this
                // is called, all we can do here is suppress the exception.
                try 
                {
                    m_contingentProperties.m_cancellationRegistration.Value.Dispose(); 
                } 
                catch (ObjectDisposedException) { }
 
                m_contingentProperties.m_cancellationRegistration = null;
            }
        }
 

        // Static delegate to be used as a cancellation callback on unstarted tasks that have a valid cancellation token. 
        // This is necessary to transition them into canceled state if their cancellation token is signalled while they are still not queued 
        internal static Action s_taskCancelCallback = new Action(TaskCancelCallback);
        private static void TaskCancelCallback(Object o) 
        {
            Task t = (Task)o;
            t.InternalCancel(false);
        } 

        // Debugger support 
        private string DebuggerDisplayMethodDescription 
        {
            get 
            {
                Delegate d = (Delegate)m_action;
                return d != null ? d.Method.ToString() : "{null}";
            } 
        }
 
 
        /// 
        /// Captures the ExecutionContext so long as flow isn't suppressed. 
        /// 
        /// A stack crawl mark pointing to the frame of the caller.

        [SecuritySafeCritical] 
        internal void PossiblyCaptureContext(ref StackCrawlMark stackMark)
        { 
            if (!ExecutionContext.IsFlowSuppressed()) 
            {
                // In the legacy .NET 3.5 build, we don't have the optimized overload of Capture() 
                // available, so we call the parameterless overload.
#if PFX_LEGACY_3_5
                m_capturedContext = ExecutionContext.Capture();
#else 
                m_capturedContext = ExecutionContext.Capture(
                    ref stackMark, 
                    ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase); 
#endif
            } 
        }

        // Internal property to process TaskCreationOptions access and mutation.
        internal TaskCreationOptions Options 
        {
            get 
            { 
                Contract.Assert((OptionsMask & 1) == 1, "OptionsMask needs a shift in Options.get");
                return (TaskCreationOptions)(m_stateFlags & OptionsMask); 
            }
        }

        // Atomically OR-in newBits to m_stateFlags, while making sure that 
        // no illegalBits are set.  Returns true on success, false on failure.
        internal bool AtomicStateUpdate(int newBits, int illegalBits) 
        { 
            int oldFlags = 0;
            return AtomicStateUpdate(newBits, illegalBits, ref oldFlags); 
        }

        internal bool AtomicStateUpdate(int newBits, int illegalBits, ref int oldFlags)
        { 
            SpinWait sw = new SpinWait();
 
            do 
            {
                oldFlags = m_stateFlags; 
                if ((oldFlags & illegalBits) != 0) return false;
                if (Interlocked.CompareExchange(ref m_stateFlags, oldFlags | newBits, oldFlags) == oldFlags)
                {
                    return true; 
                }
                sw.SpinOnce(); 
            } while (true); 

        } 

        // Atomically mark a Task as started while making sure that it is not canceled.
        internal bool MarkStarted()
        { 
            return AtomicStateUpdate(TASK_STATE_STARTED, TASK_STATE_CANCELED | TASK_STATE_STARTED);
        } 
 

        ///  
        /// Internal function that will be called by a new child task to add itself to
        /// the children list of the parent (this).
        ///
        /// Since a child task can only be created from the thread executing the action delegate 
        /// of this task, reentrancy is neither required nor supported. This should not be called from
        /// anywhere other than the task construction/initialization codepaths. 
        ///  
        internal void AddNewChild()
        { 
            Contract.Assert(Task.InternalCurrent == this || this.IsSelfReplicatingRoot, "Task.AddNewChild(): Called from an external context");

            LazyInitializer.EnsureInitialized(ref m_contingentProperties, s_contingentPropertyCreator);
 

            if (m_contingentProperties.m_completionCountdown == 1 && !IsSelfReplicatingRoot) 
            { 
                // A count of 1 indicates so far there was only the parent, and this is the first child task
                // Single kid => no fuss about who else is accessing the count. Let's save ourselves 100 cycles 
                // We exclude self replicating root tasks from this optimization, because further child creation can take place on
                // other cores and with bad enough timing this write may not be visible to them.
                m_contingentProperties.m_completionCountdown++;
            } 
            else
            { 
                // otherwise do it safely 
                Interlocked.Increment(ref m_contingentProperties.m_completionCountdown);
            } 
        }

        // This is called in the case where a new child is added, but then encounters a CancellationToken-related exception.
        // We need to subtract that child from m_completionCountdown, or the parent will never complete. 
        internal void DisregardChild()
        { 
            Contract.Assert(Task.InternalCurrent == this, "Task.DisregardChild(): Called from an external context"); 
            Contract.Assert((m_contingentProperties != null) && (m_contingentProperties.m_completionCountdown >= 2), "Task.DisregardChild(): Expected parent count to be >= 2");
 
            Interlocked.Decrement(ref m_contingentProperties.m_completionCountdown);
        }

        ///  
        /// Starts the , scheduling it for execution to the current TaskScheduler. 
        ///  
        /// 
        /// A task may only be started and run only once.  Any attempts to schedule a task a second time 
        /// will result in an exception.
        /// 
        /// 
        /// The  is not in a valid state to be started. It may have already been started, 
        /// executed, or canceled, or it may have been created in a manner that doesn't support direct
        /// scheduling. 
        ///  
        /// 
        /// The  instance has been disposed. 
        /// 
        public void Start()
        {
            Start(TaskScheduler.Current); 
        }
 
        ///  
        /// Starts the , scheduling it for execution to the specified TaskScheduler. 
        /// 
        /// 
        /// A task may only be started and run only once. Any attempts to schedule a task a second time will
        /// result in an exception. 
        /// 
        ///  
        /// The TaskScheduler with which to associate 
        /// and execute this task.
        ///  
        /// 
        /// The  argument is null.
        /// 
        ///  
        /// The  is not in a valid state to be started. It may have already been started,
        /// executed, or canceled, or it may have been created in a manner that doesn't support direct 
        /// scheduling. 
        /// 
        ///  
        /// The  instance has been disposed.
        /// 
        public void Start(TaskScheduler scheduler)
        { 
            // Throw an exception if the task has previously been disposed.
            ThrowIfDisposed(); 
 
            // Need to check this before (m_action == null) because completed tasks will
            // set m_action to null.  We would want to know if this is the reason that m_action == null. 
            if (IsCompleted)
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_Start_TaskCompleted"));
            } 

            if (m_action == null) 
            { 
                throw new InvalidOperationException(Environment.GetResourceString("Task_Start_NullAction"));
            } 

            if (scheduler == null)
            {
                throw new ArgumentNullException("scheduler"); 
            }
 
            if ((Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) != 0) 
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_Start_ContinuationTask")); 
            }


            // Make sure that Task only gets started once.  Or else throw an exception. 
            if (Interlocked.CompareExchange(ref m_taskScheduler, scheduler, null) != null)
            { 
                throw new InvalidOperationException(Environment.GetResourceString("Task_Start_AlreadyStarted")); 
            }
 
            ScheduleAndStart(true);
        }

        ///  
        /// Runs the  synchronously on the current TaskScheduler. 
        ///  
        /// 
        ///  
        /// A task may only be started and run only once. Any attempts to schedule a task a second time will
        /// result in an exception.
        /// 
        ///  
        /// Tasks executed with  will be associated with the current TaskScheduler. 
        ///  
        /// 
        /// If the target scheduler does not support running this Task on the current thread, the Task will 
        /// be scheduled for execution on the scheduler, and the current thread will block until the
        /// Task has completed execution.
        /// 
        ///  
        /// 
        /// The  is not in a valid state to be started. It may have already been started, 
        /// executed, or canceled, or it may have been created in a manner that doesn't support direct 
        /// scheduling.
        ///  
        /// 
        /// The  instance has been disposed.
        /// 
        public void RunSynchronously() 
        {
            InternalRunSynchronously(TaskScheduler.Current); 
        } 

        ///  
        /// Runs the  synchronously on the scheduler provided.
        /// 
        ///  
        /// 
        /// A task may only be started and run only once. Any attempts to schedule a task a second time will 
        /// result in an exception. 
        /// 
        ///  
        /// If the target scheduler does not support running this Task on the current thread, the Task will
        /// be scheduled for execution on the scheduler, and the current thread will block until the
        /// Task has completed execution.
        ///  
        /// 
        ///  
        /// The  is not in a valid state to be started. It may have already been started, 
        /// executed, or canceled, or it may have been created in a manner that doesn't support direct
        /// scheduling. 
        /// 
        /// 
        /// The  instance has been disposed.
        ///  
        /// The  parameter
        /// is null. 
        /// The scheduler on which to attempt to run this task inline. 
        public void RunSynchronously(TaskScheduler scheduler)
        { 
            if (scheduler == null)
            {
                throw new ArgumentNullException("scheduler");
            } 

            InternalRunSynchronously(scheduler); 
        } 

        // 
        // Internal version of RunSynchronously that allows a taskScheduler argument.
        //
        [SecuritySafeCritical] // Needed for QueueTask
        internal void InternalRunSynchronously(TaskScheduler scheduler) 
        {
            Contract.Assert(scheduler != null, "Task.InternalRunSynchronously(): null TaskScheduler"); 
            ThrowIfDisposed(); 

            // Can't call this method on a continuation task 
            if ((Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) != 0)
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_Continuation"));
            } 

            // Can't call this method on a task that has already completed 
            if (IsCompleted) 
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_TaskCompleted")); 
            }

            // Can't call this method on a promise-style task
            if (m_action == null) 
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_Promise")); 
            } 

            // Make sure that Task only gets started once.  Or else throw an exception. 
            if (Interlocked.CompareExchange(ref m_taskScheduler, scheduler, null) != null)
            {
                throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_AlreadyStarted"));
            } 

            // execute only if we win the ---- against concurrent cancel attempts. 
            // otherwise throw an exception, because we've been canceled. 
            if (MarkStarted())
            { 
                bool taskQueued = false;
                try
                {
                    // We wrap TryRunInline() in a try/catch block and move an excepted task to Faulted here, 
                    // but not in Wait()/WaitAll()/FastWaitAll().  Here, we know for sure that the
                    // task will not be subsequently scheduled (assuming that the scheduler adheres 
                    // to the guideline that an exception implies that no state change took place), 
                    // so it is safe to catch the exception and move the task to a final state.  The
                    // same cannot be said for Wait()/WaitAll()/FastWaitAll(). 
                    if (!scheduler.TryRunInline(this, false))
                    {
                        scheduler.QueueTask(this);
                        taskQueued = true; // only mark this after successfully queuing the task. 
                    }
 
                    // A successful TryRunInline doesn't guarantee completion, as there may be unfinished children 
                    // Also if we queued the task above, we need to wait.
                    if (!IsCompleted) 
                    {
                        CompletedEvent.Wait();
                    }
                } 
                catch (Exception e)
                { 
                    // we 1) either received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown 
                    //    2) or a a ThreadAbortException, which we need to skip here, because it would already have been handled in Task.Execute
                    if (!taskQueued && !(e is ThreadAbortException)) 
                    {
                        // We had a problem with TryRunInline() or QueueTask().
                        // Record the exception, marking ourselves as Completed/Faulted.
                        TaskSchedulerException tse = new TaskSchedulerException(e); 
                        AddException(tse);
                        Finish(false); 
 
                        // Mark ourselves as "handled" to avoid crashing the finalizer thread if the caller neglects to
                        // call Wait() on this task. 
                        // m_contingentProperties.m_exceptionHolder *should* already exist after AddException()
                        Contract.Assert((m_contingentProperties != null) && (m_contingentProperties.m_exceptionsHolder != null),
                            "Task.InternalRunSynchronously(): Expected m_contingentProperties.m_exceptionsHolder to exist");
                        m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false); 

                        // And re-throw. 
                        throw tse; 
                    }
                    else 
                    {
                        // We had a problem with CompletedEvent.Wait().  Just re-throw.
                        throw;
                    } 
                }
            } 
            else 
            {
                Contract.Assert((m_stateFlags & TASK_STATE_CANCELED) != 0, "Task.RunSynchronously: expected TASK_STATE_CANCELED to be set"); 
                // Can't call this method on canceled task.
                throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_TaskCompleted"));
            }
        } 

 
        //// 
        //// Helper methods for Factory StartNew methods.
        //// 


        // Implicitly converts action to object and handles the meat of the StartNew() logic.
        internal static Task InternalStartNew( 
            Task creatingTask, object action, object state, CancellationToken cancellationToken, TaskScheduler scheduler,
            TaskCreationOptions options, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark) 
        { 
            // Validate arguments.
            if (scheduler == null) 
            {
                throw new ArgumentNullException("scheduler");
            }
 
            // Create and schedule the task. This throws an InvalidOperationException if already shut down.
            // Here we add the InternalTaskOptions.QueuedByRuntime to the internalOptions, so that TaskConstructorCore can skip the cancellation token registration 
            Task t = new Task(action, state, creatingTask, cancellationToken, options, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler); 
            t.PossiblyCaptureContext(ref stackMark);
 
            t.ScheduleAndStart(false);
            return t;
        }
 
        // Variant of InternalStartNew that takes an existing context.
        internal static Task InternalStartNew( 
            Task creatingTask, object action, object state, TaskScheduler scheduler, TaskCreationOptions options, 
            InternalTaskOptions internalOptions, ExecutionContext context)
        { 
            // Validate arguments.
            if (scheduler == null)
            {
                throw new ArgumentNullException("scheduler"); 
            }
 
            // Create and schedule the task. This throws an InvalidOperationException if already shut down. 

            // Here we add the InternalTaskOptions.QueuedByRuntime to the task's options, so that TaskConstructorCore can skip the cancellation token registration 
            Task t = new Task(action, state, creatingTask, CancellationToken.None, options, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
            t.m_capturedContext = context;

            t.ScheduleAndStart(false); 
            return t;
        } 
 

 
        /////////////
        // properties

        ///  
        /// Gets a unique ID for this Task instance.
        ///  
        ///  
        /// Task IDs are assigned on-demand and do not necessarily represent the order in the which Task
        /// instances were created. 
        /// 
        public int Id
        {
            get 
            {
                if (m_taskId == 0) 
                { 
                    int newId = 0;
                    // We need to repeat if Interlocked.Increment wraps around and returns 0. 
                    // Otherwise next time this task's Id is queried it will get a new value
                    do
                    {
                        newId = Interlocked.Increment(ref s_taskIdCounter); 
                    }
                    while (newId == 0); 
 
                    Interlocked.CompareExchange(ref m_taskId, newId, 0);
                } 

                return m_taskId;
            }
        } 

        ///  
        /// Returns the unique ID of the currently executing Task. 
        /// 
        public static int? CurrentId 
        {
            get
            {
                Task currentTask = InternalCurrent; 
                if (currentTask != null)
                    return currentTask.Id; 
                else 
                    return null;
            } 
        }

        /// 
        /// Gets the Task instance currently executing, or 
        /// null if none exists.
        ///  
        internal static Task InternalCurrent 
        {
            get { return ThreadLocals.s_currentTask; } 
        }

        /// 
        /// Gets the StackGuard object assigned to the current thread. 
        /// 
        internal static StackGuard CurrentStackGuard 
        { 
            get
            { 
                StackGuard sg = ThreadLocals.s_stackGuard;
                if (sg == null)
                {
                    sg = new StackGuard(); 
                    ThreadLocals.s_stackGuard = sg;
                } 
 
                return sg;
            } 
        }


        ///  
        /// Gets the Exception that caused the Task to end prematurely. If the Task completed successfully or has not yet thrown any 
        /// exceptions, this will return null.
        ///  
        /// 
        /// Tasks that throw unhandled exceptions store the resulting exception and propagate it wrapped in a
        ///  in calls to Wait
        /// or in accesses to the  property.  Any exceptions not observed by the time 
        /// the Task instance is garbage collected will be propagated on the finalizer thread.
        ///  
        ///  
        /// The Task
        /// has been disposed. 
        /// 
        public AggregateException Exception
        {
            get 
            {
                AggregateException e = null; 
 
                // If you're faulted, retrieve the exception(s)
                if (IsFaulted) e = GetExceptions(false); 

                // Only return an exception in faulted state (skip manufactured exceptions)
                // A "benevolent" race condition makes it possible to return null when IsFaulted is
                // true (i.e., if IsFaulted is set just after the check to IsFaulted above). 
                Contract.Assert((e == null) || IsFaulted, "Task.Exception_get(): returning non-null value when not Faulted");
 
                return e; 
            }
        } 

        /// 
        /// Gets the TaskStatus of this Task.
        ///  
        public TaskStatus Status
        { 
            get 
            {
                TaskStatus rval; 

                // get a cached copy of the state flags.  This should help us
                // to get a consistent view of the flags if they are changing during the
                // execution of this method. 
                int sf = m_stateFlags;
 
                if ((sf & TASK_STATE_FAULTED) != 0) rval = TaskStatus.Faulted; 
                else if ((sf & TASK_STATE_CANCELED) != 0) rval = TaskStatus.Canceled;
                else if ((sf & TASK_STATE_RAN_TO_COMPLETION) != 0) rval = TaskStatus.RanToCompletion; 
                else if ((sf & TASK_STATE_WAITING_ON_CHILDREN) != 0) rval = TaskStatus.WaitingForChildrenToComplete;
                else if ((sf & TASK_STATE_DELEGATE_INVOKED) != 0) rval = TaskStatus.Running;
                else if ((sf & TASK_STATE_STARTED) != 0) rval = TaskStatus.WaitingToRun;
                else if ((sf & TASK_STATE_WAITINGFORACTIVATION) != 0) rval = TaskStatus.WaitingForActivation; 
                else rval = TaskStatus.Created;
 
                return rval; 
            }
        } 

        /// 
        /// Gets whether this Task instance has completed
        /// execution due to being canceled. 
        /// 
        ///  
        /// A Task will complete in Canceled state either if its CancellationToken 
        /// was marked for cancellation before the task started executing, or if the task acknowledged the cancellation request on
        /// its already signaled CancellationToken by throwing an 
        /// OperationCanceledException that bears the same
        /// CancellationToken.
        /// 
        public bool IsCanceled 
        {
            get 
            { 
                // Return true if canceled bit is set and faulted bit is not set
                return (m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_FAULTED)) == TASK_STATE_CANCELED; 
            }
        }

        ///  
        /// Returns true if this task has a cancellation token and it was signaled.
        /// To be used internally in execute entry codepaths. 
        ///  
        internal bool IsCancellationRequested
        { 
            get
            {
                // check both the internal cancellation request flag and the CancellationToken attached to this task
                return ((m_contingentProperties != null) && (m_contingentProperties.m_internalCancellationRequested == CANCELLATION_REQUESTED)) || 
                    CancellationToken.IsCancellationRequested;
            } 
        } 

        // Static delegate used for creating a ContingentProperties object from LazyInitializer. 
        internal static Func s_contingentPropertyCreator = new Func(ContingentPropertyCreator);
        private static ContingentProperties ContingentPropertyCreator()
        {
            return new ContingentProperties(); 
        }
 
        ///  
        /// This internal property provides access to the CancellationToken that was set on the task
        /// when it was constructed. 
        /// 
        internal CancellationToken CancellationToken
        {
            get 
            {
                return (m_contingentProperties == null) ? CancellationToken.None : 
                                                            m_contingentProperties.m_cancellationToken; 
            }
        } 

        /// 
        /// Gets whether this  threw an OperationCanceledException while its CancellationToken was signaled.
        ///  
        internal bool IsCancellationAcknowledged
        { 
            get { return (m_stateFlags & TASK_STATE_CANCELLATIONACKNOWLEDGED) != 0; } 
        }
 

        /// 
        /// Gets whether this Task has completed.
        ///  
        /// 
        ///  will return true when the Task is in one of the three 
        /// final states: RanToCompletion, 
        /// Faulted, or
        /// Canceled. 
        /// 
        public bool IsCompleted
        {
            get 
            {
                return ((m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_FAULTED | TASK_STATE_RAN_TO_COMPLETION)) != 0); 
            } 
        }
 
        // For use in InternalWait -- marginally faster than (Task.Status == TaskStatus.RanToCompletion)
        internal bool CompletedSuccessfully
        {
            get 
            {
                int completedMask = TASK_STATE_CANCELED | TASK_STATE_FAULTED | TASK_STATE_RAN_TO_COMPLETION; 
                return (m_stateFlags & completedMask) == TASK_STATE_RAN_TO_COMPLETION; 
            }
        } 

        /// 
        /// Checks whether this task has been disposed.
        ///  
        internal bool IsDisposed
        { 
            get { return (m_stateFlags & TASK_STATE_DISPOSED) != 0; } 
        }
 
        /// 
        /// Throws an exception if the task has been disposed, and hence can no longer be accessed.
        /// 
        /// The task has been disposed. 
        internal void ThrowIfDisposed()
        { 
            if (IsDisposed) 
            {
                throw new ObjectDisposedException(null, Environment.GetResourceString("Task_ThrowIfDisposed")); 
            }
        }

 
        /// 
        /// Gets the TaskCreationOptions used 
        /// to create this task. 
        /// 
        public TaskCreationOptions CreationOptions 
        {
            get { return Options & (TaskCreationOptions)(~InternalTaskOptions.InternalOptionsMask); }
        }
 
        /// 
        /// Gets a  that can be used to wait for the task to 
        /// complete. 
        /// 
        ///  
        /// Using the wait functionality provided by 
        /// should be preferred over using  for similar
        /// functionality.
        ///  
        /// 
        /// The  has been disposed. 
        ///  
        WaitHandle IAsyncResult.AsyncWaitHandle
        { 
            // Although a slim event is used internally to avoid kernel resource allocation, this function
            // forces allocation of a true WaitHandle when called.
            get
            { 
                ThrowIfDisposed();
                return CompletedEvent.WaitHandle; 
            } 
        }
 
        // Overridden by Task to return m_futureState
        internal virtual object InternalAsyncState
        {
            get { return m_stateObject; } 
        }
 
        ///  
        /// Gets the state object supplied when the Task was created,
        /// or null if none was supplied. 
        /// 
        public object AsyncState
        {
            get { return InternalAsyncState; } 
        }
 
        ///  
        /// Gets an indication of whether the asynchronous operation completed synchronously.
        ///  
        /// true if the asynchronous operation completed synchronously; otherwise, false.
        bool IAsyncResult.CompletedSynchronously
        {
            get 
            {
                // @ 
 
                return false;
            } 
        }

        // @
 

 
        internal TaskScheduler ExecutingTaskScheduler 
        {
            get { return m_taskScheduler; } 
        }

        /// 
        /// Provides access to factory methods for creating  and  instances. 
        /// 
        ///  
        /// The factory returned from  is a default instance 
        /// of , as would result from using
        /// the default constructor on TaskFactory. 
        /// 
        public static TaskFactory Factory { get { return s_factory; } }

        ///  
        /// Provides an event that can be used to wait for completion.
        /// Only called by Wait*(), which means that we really do need to instantiate a completion event. 
        ///  
        internal ManualResetEventSlim CompletedEvent
        { 
            get
            {
                if (m_completionEvent == null)
                { 
                    bool wasCompleted = IsCompleted;
                    ManualResetEventSlim newMre = new ManualResetEventSlim(wasCompleted); 
                    if (Interlocked.CompareExchange(ref m_completionEvent, newMre, null) != null) 
                    {
                        // We lost the ----, so we will just close the event right away. 
                        newMre.Dispose();
                    }
                    else if (!wasCompleted && IsCompleted)
                    { 
                        // We published the event as unset, but the task has subsequently completed.
                        // Set the event's state properly so that callers don't deadlock. 
                        newMre.Set(); 
                    }
                } 

                return m_completionEvent;
            }
        } 

        ///  
        /// Sets the internal completion event. 
        /// 
        private void SetCompleted() 
        {

            ManualResetEventSlim mres = m_completionEvent;
            if (mres != null) 
            {
                mres.Set(); 
            } 
        }
 
        /// 
        /// Determines whether this is the root task of a self replicating group.
        /// 
        internal bool IsSelfReplicatingRoot 
        {
            get 
            { 
                return ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0) &&
                        ((Options & (TaskCreationOptions)InternalTaskOptions.ChildReplica) == 0); 
            }
        }

        ///  
        /// Determines whether the task is a replica itself.
        ///  
        internal bool IsChildReplica 
        {
            get { return (Options & (TaskCreationOptions)InternalTaskOptions.ChildReplica) != 0; } 
        }

        internal int ActiveChildCount
        { 
            get { return m_contingentProperties != null ? m_contingentProperties.m_completionCountdown - 1 : 0; }
        } 
 
        /// 
        /// The property formerly known as IsFaulted. 
        /// 
        internal bool ExceptionRecorded
        {
            get { return (m_contingentProperties != null) && (m_contingentProperties.m_exceptionsHolder != null); } 
        }
 
        ///  
        /// Gets whether the  completed due to an unhandled exception.
        ///  
        /// 
        /// If  is true, the Task's  will be equal to
        /// TaskStatus.Faulted, and its
        ///  property will be non-null. 
        /// 
        public bool IsFaulted 
        { 
            get
            { 
                // Faulted is "king" -- if that bit is present (regardless of other bits), we are faulted.
                return ((m_stateFlags & TASK_STATE_FAULTED) != 0);
            }
        } 

 
#if DEBUG 
        /// 
        /// Retrieves an identifier for the task. 
        /// 
        internal int InternalId
        {
            get { return GetHashCode(); } 
        }
#endif 
 
        /////////////
        // methods 


        /// 
        /// Disposes the , releasing all of its unmanaged resources. 
        /// 
        ///  
        /// Unlike most of the members of , this method is not thread-safe. 
        /// Also,  may only be called on a  that is in one of
        /// the final states: RanToCompletion, 
        /// Faulted, or
        /// Canceled.
        /// 
        ///  
        /// The exception that is thrown if the  is not in
        /// one of the final states: RanToCompletion, 
        /// Faulted, or 
        /// Canceled.
        ///  
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this); 
        }
 
        ///  
        /// Disposes the , releasing all of its unmanaged resources.
        ///  
        /// 
        /// A Boolean value that indicates whether this method is being called due to a call to .
        ///  
        /// 
        /// Unlike most of the members of , this method is not thread-safe. 
        ///  
        protected virtual void Dispose(bool disposing)
        { 
            if (disposing)
            {
                // Task must be completed to dispose
                if (!IsCompleted) 
                {
                    throw new InvalidOperationException(Environment.GetResourceString("Task_Dispose_NotCompleted")); 
                } 

                var tmp = m_completionEvent; // make a copy to protect against racing Disposes. 

                // Dispose of the underlying completion event
                if (tmp != null)
                { 
                    // In the unlikely event that our completion event is inflated but not yet signaled,
                    // go ahead and signal the event.  If you dispose of an unsignaled MRES, then any waiters 
                    // will deadlock; an ensuing Set() will not wake them up.  In the event of an AppDomainUnload, 
                    // there is no guarantee that anyone else is going to signal the event, and it does no harm to
                    // call Set() twice on m_completionEvent. 
                    if (!tmp.IsSet) tmp.Set();

                    tmp.Dispose();
                    m_completionEvent = null; 
                }
 
            } 

            // We OR the flags to indicate the object has been disposed.  This is not 
            // thread-safe -- trying to dispose while a task is running can lead to corruption.
            // Do this regardless of the value of "disposing".
            m_stateFlags |= TASK_STATE_DISPOSED;
        } 

        ///////////// 
        // internal helpers 

 
        /// 
        /// Schedules the task for execution.
        /// 
        /// If true, TASK_STATE_STARTED bit is turned on in 
        /// an atomic fashion, making sure that TASK_STATE_CANCELED does not get set
        /// underneath us.  If false, TASK_STATE_STARTED bit is OR-ed right in.  This 
        /// allows us to streamline things a bit for StartNew(), where competing cancellations 
        /// are not a problem.
        [SecuritySafeCritical] // Needed for QueueTask 
        internal void ScheduleAndStart(bool needsProtection)
        {
            Contract.Assert(m_taskScheduler != null, "expected a task scheduler to have been selected");
            Contract.Assert((m_stateFlags & TASK_STATE_STARTED) == 0, "task has already started"); 

            // Set the TASK_STATE_STARTED bit 
            if (needsProtection) 
            {
                if (!MarkStarted()) 
                {
                    // A cancel has snuck in before we could get started.  Quietly exit.
                    return;
                } 
            }
            else 
            { 
                m_stateFlags |= TASK_STATE_STARTED;
            } 

            try
            {
                // Queue to the indicated scheduler. 
                m_taskScheduler.QueueTask(this);
            } 
            catch (ThreadAbortException tae) 
            {
                AddException(tae); 
                FinishThreadAbortedTask(true, false);
            }
            catch (Exception e)
            { 
                // The scheduler had a problem queueing this task.  Record the exception, leaving this task in
                // a Faulted state. 
                TaskSchedulerException tse = new TaskSchedulerException(e); 
                AddException(tse);
                Finish(false); 

                // Now we need to mark ourselves as "handled" to avoid crashing the finalizer thread if we are called from StartNew()
                // or from the self replicating logic, because in both cases the exception is either propagated outside directly, or added
                // to an enclosing parent. However we won't do this for continuation tasks, because in that case we internally eat the exception 
                // and therefore we need to make sure the user does later observe it explicitly or see it on the finalizer.
 
                if ((Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0) 
                {
                    // m_contingentProperties.m_exceptionHolder *should* already exist after AddException() 
                    Contract.Assert((m_contingentProperties != null) && (m_contingentProperties.m_exceptionsHolder != null),
                            "Task.InternalRunSynchronously(): Expected m_contingentProperties.m_exceptionsHolder to exist");

                    m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false); 
                }
 
                // re-throw the exception wrapped as a TaskSchedulerException. 
                throw tse;
            } 
        }


        ///  
        /// Adds an exception to the list of exceptions this task has thrown.
        ///  
        /// An object representing either an Exception or a collection of Exceptions. 
        internal void AddException(object exceptionObject)
        { 
            //
            // WARNING: A great deal of care went into insuring that
            // AddException() and GetExceptions() are never called
            // simultaneously.  See comment at start of GetExceptions(). 
            //
 
            // Lazily initialize the list, ensuring only one thread wins. 
            LazyInitializer.EnsureInitialized(ref m_contingentProperties, s_contingentPropertyCreator);
            if (m_contingentProperties.m_exceptionsHolder == null) 
            {
                TaskExceptionHolder holder = new TaskExceptionHolder(this);
                if (Interlocked.CompareExchange(
                    ref m_contingentProperties.m_exceptionsHolder, holder, null) != null) 
                {
                    // If we lost the ----, suppress finalization. 
                    holder.MarkAsHandled(false); 
                }
            } 

            // Figure this out before your enter the lock.
            Contract.Assert((exceptionObject is Exception) || (exceptionObject is IEnumerable),
                "Task.AddException: Expected an Exception or an IEnumerable"); 

            lock (m_contingentProperties) 
            { 
                m_contingentProperties.m_exceptionsHolder.Add(exceptionObject);
            } 

        }

 
        /// 
        /// Returns a list of exceptions by aggregating the holder's contents. Or null if 
        /// no exceptions have been thrown. 
        /// 
        /// Whether to include a TCE if cancelled. 
        /// An aggregate exception, or null if no exceptions have been caught.
        private AggregateException GetExceptions(bool includeTaskCanceledExceptions)
        {
            // 
            // WARNING: The Task/Task/TaskCompletionSource classes
            // have all been carefully crafted to insure that GetExceptions() 
            // is never called while AddException() is being called.  There 
            // are locks taken on m_contingentProperties in several places:
            // 
            // -- Task.TrySetException(): The lock allows the
            //    task to be set to Faulted state, and all exceptions to
            //    be recorded, in one atomic action.
            // 
            // -- Task.Exception_get(): The lock ensures that Task.TrySetException()
            //    is allowed to complete its operation before Task.Exception_get() 
            //    can access GetExceptions(). 
            //
            // -- Task.ThrowIfExceptional(): The lock insures that Wait() will 
            //    not attempt to call GetExceptions() while Task.TrySetException()
            //    is in the process of calling AddException().
            //
            // For "regular" tasks, we effectively keep AddException() and GetException() 
            // from being called concurrently by the way that the state flows.  Until
            // a Task is marked Faulted, Task.Exception_get() returns null.  And 
            // a Task is not marked Faulted until it and all of its children have 
            // completed, which means that all exceptions have been recorded.
            // 
            // It might be a lot easier to follow all of this if we just required
            // that all calls to GetExceptions() and AddExceptions() were made
            // under a lock on m_contingentProperties.  But that would also
            // increase our lock occupancy time and the frequency with which we 
            // would need to take the lock.
            // 
            // If you add a call to GetExceptions() anywhere in the code, 
            // please continue to maintain the invariant that it can't be
            // called when AddException() is being called. 
            //

            // We'll lazily create a TCE if the task has been canceled.
            Exception canceledException = null; 
            if (includeTaskCanceledExceptions && IsCanceled)
            { 
                canceledException = new TaskCanceledException(this); 
            }
 
            if (ExceptionRecorded)
            {
                // There are exceptions; get the aggregate and optionally add the canceled
                // exception to the aggregate (if applicable). 
                Contract.Assert(m_contingentProperties != null); // ExceptionRecorded ==> m_contingentProperties != null
 
                // No need to lock around this, as other logic prevents the consumption of exceptions 
                // before they have been completely processed.
                return m_contingentProperties.m_exceptionsHolder.CreateExceptionObject(false, canceledException); 
            }
            else if (canceledException != null)
            {
                // No exceptions, but there was a cancelation. Aggregate and return it. 
                return new AggregateException(canceledException);
            } 
 
            return null;
        } 

        /// 
        /// Throws an aggregate exception if the task contains exceptions.
        ///  
        internal void ThrowIfExceptional(bool includeTaskCanceledExceptions)
        { 
            Contract.Assert(IsCompleted, "ThrowIfExceptional(): Expected IsCompleted == true"); 

            Exception exception = GetExceptions(includeTaskCanceledExceptions); 
            if (exception != null)
            {
                UpdateExceptionObservedStatus();
                throw exception; 
            }
        } 
 
        /// 
        /// Checks whether this is an attached task, and whether we are being called by the parent task. 
        /// And sets the TASK_STATE_EXCEPTIONOBSERVEDBYPARENT status flag based on that.
        ///
        /// This is meant to be used internally when throwing an exception, and when WaitAll is gathering
        /// exceptions for tasks it waited on. If this flag gets set, the implicit wait on children 
        /// will skip exceptions to prevent duplication.
        /// 
        /// This should only be called when this task has completed with an exception 
        ///
        ///  
        internal void UpdateExceptionObservedStatus()
        {
            if ((Options & TaskCreationOptions.AttachedToParent) != 0 &&
                 Task.InternalCurrent == m_parent) 
            {
                m_stateFlags |= TASK_STATE_EXCEPTIONOBSERVEDBYPARENT; 
            } 
        }
 
        /// 
        /// Checks whether the TASK_STATE_EXCEPTIONOBSERVEDBYPARENT status flag is set,
        /// This will only be used by the implicit wait to prevent double throws
        /// 
        /// 
        internal bool IsExceptionObservedByParent 
        { 
            get
            { 
                return (m_stateFlags & TASK_STATE_EXCEPTIONOBSERVEDBYPARENT) != 0;
            }
        }
 
        /// 
        /// Checks whether the body was ever invoked. Used by task scheduler code to verify custom schedulers actually ran the task. 
        ///  
        internal bool IsDelegateInvoked
        { 
            get
            {
                return (m_stateFlags & TASK_STATE_DELEGATE_INVOKED) != 0;
            } 
        }
 
        ///  
        /// Signals completion of this particular task.
        /// 
        /// The bUserDelegateExecuted parameter indicates whether this Finish() call comes following the
        /// full execution of the user delegate.
        ///
        /// If bUserDelegateExecuted is false, it mean user delegate wasn't invoked at all (either due to 
        /// a cancellation request, or because this task is a promise style Task). In this case, the steps
        /// involving child tasks (i.e. WaitForChildren) will be skipped. 
        /// 
        /// 
        internal void Finish(bool bUserDelegateExecuted) 
        {

            if (!bUserDelegateExecuted)
            { 
                // delegate didn't execute => no children. We can safely call the remaining finish stages
                FinishStageTwo(); 
            } 
            else
            { 
                ContingentProperties properties = m_contingentProperties;

                if (properties == null ||                    // no contingent properties, no children. Safe to complete ourselves
                    (properties.m_completionCountdown == 1 && !IsSelfReplicatingRoot) || 
                    // Count of 1 => either all children finished, or there were none. Safe to complete ourselves
                    // without paying the price of an Interlocked.Decrement. 
                    // However we need to exclude self replicating root tasks from this optimization, because 
                    // they can have children joining in, or finishing even after the root task delegate is done.
                    Interlocked.Decrement(ref properties.m_completionCountdown) == 0) // Reaching this sub clause means there may be remaining active children, 
                // and we could be racing with one of them to call FinishStageTwo().
                // So whoever does the final Interlocked.Dec is responsible to finish.
                {
 
                    FinishStageTwo();
                } 
                else 
                {
                    // Apparently some children still remain. It will be up to the last one to process the completion of this task on their own thread. 
                    // We will now yield the thread back to ThreadPool. Mark our state appropriately before getting out.

                    // We have to use an atomic update for this and make sure not to overwrite a final state,
                    // because at this very moment the last child's thread may be concurrently completing us. 
                    // Otherwise we risk overwriting the TASK_STATE_RAN_TO_COMPLETION, _CANCELED or _FAULTED bit which may have been set by that child task.
                    // Note that the concurrent update by the last child happening in FinishStageTwo could still wipe out the TASK_STATE_WAITING_ON_CHILDREN flag, 
                    // but it is not critical to maintain, therefore we dont' need to intruduce a full atomic update into FinishStageTwo 

                    AtomicStateUpdate(TASK_STATE_WAITING_ON_CHILDREN, TASK_STATE_FAULTED | TASK_STATE_CANCELED | TASK_STATE_RAN_TO_COMPLETION); 
                }
            }

            // Now is the time to prune exceptional children. We'll walk the list and removes the ones whose exceptions we might have observed after they threw. 
            // we use a local variable for exceptional children here because some other thread may be nulling out m_contingentProperties.m_exceptionalChildren
            List exceptionalChildren = m_contingentProperties != null ? m_contingentProperties.m_exceptionalChildren : null; 
 
            if (exceptionalChildren != null)
            { 
                lock (exceptionalChildren)
                {
                    exceptionalChildren.RemoveAll(s_IsExceptionObservedByParentPredicate); // RemoveAll has better performance than doing it ourselves
                } 
            }
        } 
 
        // statically allocated delegate for the removeall expression in Finish()
        private static Predicate s_IsExceptionObservedByParentPredicate = new Predicate((t) => { return t.IsExceptionObservedByParent; }); 

        /// 
        /// FinishStageTwo is to be executed as soon as we known there are no more children to complete.
        /// It can happen i) either on the thread that originally executed this task (if no children were spawned, or they all completed by the time this task's delegate quit) 
        ///              ii) or on the thread that executed the last child.
        ///  
        internal void FinishStageTwo() 
        {
            AddExceptionsFromChildren(); 

            // At this point, the task is done executing and waiting for its children,
            // we can transition our task to a completion state.
            int completionState; 
            if (ExceptionRecorded)
            { 
                completionState = TASK_STATE_FAULTED; 
            }
            else if (IsCancellationRequested && IsCancellationAcknowledged) 
            {
                // We transition into the TASK_STATE_CANCELED final state if the task's CT was signalled for cancellation,
                // and the user delegate acknowledged the cancellation request by throwing an OCE,
                // and the task hasn't otherwise transitioned into faulted state. (TASK_STATE_FAULTED trumps TASK_STATE_CANCELED) 
                //
                // If the task threw an OCE without cancellation being requestsed (while the CT not being in signaled state), 
                // then we regard it as a regular exception 

                completionState = TASK_STATE_CANCELED; 
            }
            else
            {
                completionState = TASK_STATE_RAN_TO_COMPLETION; 
            }
 
            // Use Interlocked.Exchange() to effect a memory fence, preventing 
            // any SetCompleted() (or later) instructions from sneak back before it.
            Interlocked.Exchange(ref m_stateFlags, m_stateFlags | completionState); 

            // Set the completion event if it's been lazy allocated.
            SetCompleted();
 
            // if we made a cancellation registration, it's now unnecessary.
            DeregisterCancellationCallback(); 
 
            // ready to run continuations and notify parent.
            FinishStageThree(); 
        }


        ///  
        /// Final stage of the task completion code path. Notifies the parent (if any) that another of its childre are done, and runs continuations.
        /// This function is only separated out from FinishStageTwo because these two operations are also needed to be called from CancellationCleanupLogic() 
        ///  
        private void FinishStageThree()
        { 
            // Notify parent if this was an attached task
            if (m_parent != null
                && (((TaskCreationOptions)(m_stateFlags & OptionsMask)) & TaskCreationOptions.AttachedToParent) != 0)
            { 
                m_parent.ProcessChildCompletion(this);
            } 
 
            // Activate continuations (if any).
            FinishContinuations(); 

            // Need this to bound the memory usage on long/infinite continuation chains
            m_action = null;
        } 

        ///  
        /// This is called by children of this task when they are completed. 
        /// 
        internal void ProcessChildCompletion(Task childTask) 
        {
            Contract.Assert(childTask.m_parent == this, "ProcessChildCompletion should only be called for a child of this task");
            Contract.Assert(childTask.IsCompleted, "ProcessChildCompletion was called for an uncompleted task");
 
            // if the child threw and we haven't observed it we need to save it for future reference
            if (childTask.IsFaulted && !childTask.IsExceptionObservedByParent) 
            { 
                // Lazily initialize the child exception list
                if (m_contingentProperties.m_exceptionalChildren == null) 
                {
                    Interlocked.CompareExchange(ref m_contingentProperties.m_exceptionalChildren, new List(), null);
                }
 
                // In rare situations involving AppDomainUnload, it's possible (though unlikely) for FinishStageTwo() to be called
                // multiple times for the same task.  In that case, AddExceptionsFromChildren() could be nulling m_exceptionalChildren 
                // out at the same time that we're processing it, resulting in a NullReferenceException here.  We'll protect 
                // ourselves by caching m_exceptionChildren in a local variable.
                List tmp = m_contingentProperties.m_exceptionalChildren; 
                if (tmp != null)
                {
                    lock (tmp)
                    { 
                        tmp.Add(childTask);
                    } 
                } 

            } 

            if (Interlocked.Decrement(ref m_contingentProperties.m_completionCountdown) == 0)
            {
                // This call came from the final child to complete, and apparently we have previously given up this task's right to complete itself. 
                // So we need to invoke the final finish stage.
 
                FinishStageTwo(); 
            }
        } 

        /// 
        /// This is to be called just before the task does its final state transition.
        /// It traverses the list of exceptional children, and appends their aggregate exceptions into this one's exception list 
        /// 
        internal void AddExceptionsFromChildren() 
        { 
            // In rare occurences during AppDomainUnload() processing, it is possible for this method to be called
            // simultaneously on the same task from two different contexts.  This can result in m_exceptionalChildren 
            // being nulled out while it is being processed, which could lead to a NullReferenceException.  To
            // protect ourselves, we'll cache m_exceptionalChildren in a local variable.
            List tmp = (m_contingentProperties != null) ? m_contingentProperties.m_exceptionalChildren : null;
 
            if (tmp != null)
            { 
                // This lock is necessary because even though AddExceptionsFromChildren is last to execute, it may still 
                // be racing with the code segment at the bottom of Finish() that prunes the exceptional child array.
                lock (tmp) 
                {
                    foreach (Task task in tmp)
                    {
                        // Ensure any exceptions thrown by children are added to the parent. 
                        // In doing this, we are implicitly marking children as being "handled".
                        Contract.Assert(task.IsCompleted, "Expected all tasks in list to be completed"); 
                        if (task.IsFaulted && !task.IsExceptionObservedByParent) 
                        {
                            TaskExceptionHolder exceptionHolder = task.m_contingentProperties.m_exceptionsHolder; 
                            Contract.Assert(exceptionHolder != null);

                            // No locking necessary since child task is finished adding exceptions
                            // and concurrent CreateExceptionObject() calls do not constitute 
                            // a concurrency hazard.
                            AddException(exceptionHolder.CreateExceptionObject(false, null)); 
                        } 
                    }
                } 

                // Reduce memory pressure by getting rid of the array
                m_contingentProperties.m_exceptionalChildren = null;
            } 
        }
 
        ///  
        /// Special purpose Finish() entry point to be used when the task delegate throws a ThreadAbortedException
        /// This makes a note in the state flags so that we avoid any costly synchronous operations in the finish codepath 
        /// such as inlined continuations
        /// 
        /// 
        /// Indicates whether the ThreadAbortException was added to this task's exception holder. 
        /// This should always be true except for the case of non-root self replicating task copies.
        ///  
        /// Whether the delegate was executed. 
        internal void FinishThreadAbortedTask(bool bTAEAddedToExceptionHolder, bool delegateRan)
        { 
            Contract.Assert(!bTAEAddedToExceptionHolder || (m_contingentProperties != null && m_contingentProperties.m_exceptionsHolder != null),
                            "FinishThreadAbortedTask() called on a task whose exception holder wasn't initialized");

            // this will only be false for non-root self replicating task copies, because all of their exceptions go to the root task. 
            if (bTAEAddedToExceptionHolder)
                m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false); 
 
            // If this method has already been called for this task, or if this task has already completed, then
            // return before actually calling Finish(). 
            if (!AtomicStateUpdate(TASK_STATE_THREAD_WAS_ABORTED,
                            TASK_STATE_THREAD_WAS_ABORTED | TASK_STATE_RAN_TO_COMPLETION | TASK_STATE_FAULTED | TASK_STATE_CANCELED))
            {
                return; 
            }
 
            Finish(delegateRan); 

        } 


        /// 
        /// Executes the task. This method will only be called once, and handles bookeeping associated with 
        /// self-replicating tasks, in addition to performing necessary exception marshaling.
        ///  
        /// The task has already been disposed. 
        private void Execute()
        { 
            if (IsSelfReplicatingRoot)
            {
                ExecuteSelfReplicating(this);
            } 
            else
            { 
                try 
                {
                    InnerInvoke(); 
                }
                catch (ThreadAbortException tae)
                {
                    // Don't record the TAE or call FinishThreadAbortedTask for a child replica task -- 
                    // it's already been done downstream.
                    if (!IsChildReplica) 
                    { 
                        // Record this exception in the task's exception list
                        HandleException(tae); 

                        // This is a ThreadAbortException and it will be rethrown from this catch clause, causing us to
                        // skip the regular Finish codepath. In order not to leave the task unfinished, we now call
                        // FinishThreadAbortedTask here. 
                        FinishThreadAbortedTask(true, true);
                    } 
                } 
                catch (Exception exn)
                { 
                    // Record this exception in the task's exception list
                    HandleException(exn);
                }
            } 
        }
 
        // Allows (internal) deriving classes to support limited replication. 
        // (By default, replication is basically unlimited).
        internal virtual bool ShouldReplicate() 
        {
            return true;
        }
 
        // Allows (internal) deriving classes to instantiate the task replica as a Task super class of their choice
        // (By default, we create a regular Task instance) 
        internal virtual Task CreateReplicaTask(Action taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler, 
                                            TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica)
        { 
            return new Task(taskReplicaDelegate, stateObject, parentTask, CancellationToken.None,
                            creationOptionsForReplica, internalOptionsForReplica, parentTask.ExecutingTaskScheduler);
        }
 
        // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
        internal virtual Object SavedStateForNextReplica 
        { 
            get { return null; }
 
            set { /*do nothing*/ }
        }

        // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica 
        internal virtual Object SavedStateFromPreviousReplica
        { 
            get { return null; } 

            set { /*do nothing*/ } 
        }

        // Allows internal deriving classes to support replicas that exit prematurely and want to hand over the child replica that they
        // had queued, so that the replacement replica can work with that child task instead of queuing up yet another one 
        internal virtual Task HandedOverChildReplica
        { 
            get { return null; } 

            set { /* do nothing*/ } 
        }

        private static void ExecuteSelfReplicating(Task root)
        { 
            TaskCreationOptions creationOptionsForReplicas = root.CreationOptions | TaskCreationOptions.AttachedToParent;
            InternalTaskOptions internalOptionsForReplicas = 
                InternalTaskOptions.ChildReplica |  // child replica flag disables self replication for the replicas themselves. 
                InternalTaskOptions.SelfReplicating |  // we still want to identify this as part of a self replicating group
                InternalTaskOptions.QueuedByRuntime;   // we queue and cancel these tasks internally, so don't allow CT registration to take place 


            // Important Note: The child replicas we launch from here will be attached the root replica (by virtue of the root.CreateReplicaTask call)
            // because we need the root task to receive all their exceptions, and to block until all of them return 

 
            // This variable is captured in a closure and shared among all replicas. 
            bool replicasAreQuitting = false;
 
            // Set up a delegate that will form the body of the root and all recursively created replicas.
            Action taskReplicaDelegate = null;
            taskReplicaDelegate = delegate
            { 
                Task currentTask = Task.InternalCurrent;
 
 
                // Check if a child task has been handed over by a prematurely quiting replica that we might be a replacement for.
                Task childTask = currentTask.HandedOverChildReplica; 

                if (childTask == null)
                {
                    // Apparently we are not a replacement task. This means we need to queue up a child task for replication to progress 

                    // Down-counts a counter in the root task. 
                    if (!root.ShouldReplicate()) return; 

                    // If any of the replicas have quit, we will do so ourselves. 
                    if (replicasAreQuitting)
                    {
                        return;
                    } 

                    // Propagate a copy of the context from the root task. It may be null if flow was suppressed. 
                    ExecutionContext creatorContext = root.m_capturedContext; 

 
                    childTask = root.CreateReplicaTask(taskReplicaDelegate, root.m_stateObject, root, root.ExecutingTaskScheduler,
                                                       creationOptionsForReplicas, internalOptionsForReplicas);

                    childTask.m_capturedContext = (creatorContext == null ? null : creatorContext.CreateCopy()); 

                    childTask.ScheduleAndStart(false); 
                } 

 

                // Finally invoke the meat of the task.
                // Note that we are directly calling root.InnerInvoke() even though we are currently be in the action delegate of a child replica
                // This is because the actual work was passed down in that delegate, and the action delegate of the child replica simply contains this 
                // replication control logic.
                try 
                { 
                    // passing in currentTask only so that the parallel debugger can find it
                    root.InnerInvokeWithArg(currentTask); 
                }
                catch (Exception exn)
                {
                    // Record this exception in the root task's exception list 
                    root.HandleException(exn);
 
                    if (exn is ThreadAbortException) 
                    {
                        // If this is a ThreadAbortException it will escape this catch clause, causing us to skip the regular Finish codepath 
                        // In order not to leave the task unfinished, we now call FinishThreadAbortedTask here
                        currentTask.FinishThreadAbortedTask(false, true);
                    }
                } 

                Object savedState = currentTask.SavedStateForNextReplica; 
 
                // check for premature exit
                if (savedState != null) 
                {
                    // the replica decided to exit early
                    // we need to queue up a replacement, attach the saved state, and yield the thread right away
 
                    Task replacementReplica = root.CreateReplicaTask(taskReplicaDelegate, root.m_stateObject, root, root.ExecutingTaskScheduler,
                                                                    creationOptionsForReplicas, internalOptionsForReplicas); 
 
                    // Propagate a copy of the context from the root task to the replacement task
                    ExecutionContext creatorContext = root.m_capturedContext; 
                    replacementReplica.m_capturedContext = (creatorContext == null ? null : creatorContext.CreateCopy());

                    replacementReplica.HandedOverChildReplica = childTask;
                    replacementReplica.SavedStateFromPreviousReplica = savedState; 

                    replacementReplica.ScheduleAndStart(false); 
                } 
                else
                { 
                    // The replica finished normally, which means it can't find more work to grab.
                    // Time to mark replicas quitting

                    replicasAreQuitting = true; 

                    // InternalCancel() could conceivably throw in the underlying scheduler's TryDequeue() method. 
                    // If it does, then make sure that we record it. 
                    try
                    { 
                        childTask.InternalCancel(true);
                    }
                    catch (Exception e)
                    { 
                        // Apparently TryDequeue threw an exception.  Before propagating that exception, InternalCancel should have
                        // attempted an atomic state transition and a call to CancellationCleanupLogic() on this task. So we know 
                        // the task was properly cleaned up if it was possible. 
                        //
                        // Now all we need to do is to Record the exception in the root task. 

                        root.HandleException(e);
                    }
 
                    // No specific action needed if the child could not be canceled
                    // because we attached it to the root task, which should therefore be receiving any exceptions from the child, 
                    // and root.wait will not return before this child finishes anyway. 

                } 
            };

            //
            // Now we execute as the root task 
            //
            taskReplicaDelegate(null); 
        } 

        ///  
        /// IThreadPoolWorkItem override, which is the entry function for this task when the TP scheduler decides to run it.
        ///
        /// 
        [SecurityCritical] 
        void IThreadPoolWorkItem.ExecuteWorkItem()
        { 
            ExecuteEntry(false); 
        }
 
        /// 
        /// The ThreadPool calls this if a ThreadAbortException is thrown while trying to execute this workitem.  This may occur
        /// before Task would otherwise be able to observe it.
        ///  
        [SecurityCritical]
        void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) 
        { 
            // If the task has marked itself as Completed, then it either a) already observed this exception (so we shouldn't handle it here)
            // or b) completed before the exception ocurred (in which case it shouldn't count against this Task). 
            if (!IsCompleted)
            {
                HandleException(tae);
                FinishThreadAbortedTask(true, false); 
            }
        } 
 
        /// 
        /// Outermost entry function to execute this task. Handles all aspects of executing a task on the caller thread. 
        /// Currently this is called by IThreadPoolWorkItem.ExecuteWorkItem(), and TaskManager.TryExecuteInline.
        ///
        /// 
        ///  Performs atomic updates to prevent double execution. Should only be set to true 
        /// in codepaths servicing user provided TaskSchedulers. The ConcRT or ThreadPool schedulers don't need this. 
        [SecuritySafeCritical] 
        internal bool ExecuteEntry(bool bPreventDoubleExecution) 
        {
            if (bPreventDoubleExecution || ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0) ) 
            {
                int previousState = 0;

                // Do atomic state transition from queued to invoked. If we observe a task that's already invoked, 
                // we will return false so that TaskScheduler.ExecuteTask can throw an exception back to the custom scheduler.
                // However we don't want this exception to be throw if the task was already canceled, because it's a 
                // legitimate scenario for custom schedulers to dequeue a task and mark it as canceled (example: throttling scheduler) 
                if (!AtomicStateUpdate(TASK_STATE_DELEGATE_INVOKED, TASK_STATE_DELEGATE_INVOKED, ref previousState)
                    && (previousState & TASK_STATE_CANCELED) == 0) 
                {
                    // This task has already been invoked.  Don't invoke it again.
                    return false;
                } 
            }
            else 
            { 
                // Remember that we started running the task delegate.
                m_stateFlags |= TASK_STATE_DELEGATE_INVOKED; 
            }

            if (!IsCancellationRequested && !IsCanceled)
            { 
                ExecuteWithThreadLocal(ref ThreadLocals.s_currentTask);
            } 
            else if (!IsCanceled) 
            {
                int prevState = Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_CANCELED); 
                if ((prevState & TASK_STATE_CANCELED) == 0)
                {
                    CancellationCleanupLogic();
                } 
            }
 
            return true; 
        }
 
        // A trick so we can refer to the TLS slot with a byref.
        [SecurityCritical]
        private void ExecuteWithThreadLocal(ref Task currentTaskSlot)
        { 
            // Remember the current task so we can restore it after running, and then
            Task previousTask = currentTaskSlot; 
 
#if !FEATURE_PAL    // PAL doesn't support  eventing
            // ETW event for Task Started 
            if (TplEtwProvider.Log.IsEnabled(EventLevel.Verbose, ((EventKeywords)(-1))))
            {
                // previousTask holds the actual "current task" we want to report in the event
                if (previousTask != null) 
                    TplEtwProvider.Log.TaskStarted(previousTask.m_taskScheduler.Id, previousTask.Id, this.Id);
                else 
                    TplEtwProvider.Log.TaskStarted(TaskScheduler.Current.Id, 0, this.Id); 
            }
#endif 

            try
            {
                // place the current task into TLS. 
                currentTaskSlot = this;
 
                ExecutionContext ec = m_capturedContext; 
                if (ec == null)
                { 
                    // No context, just run the task directly.
                    Execute();
                }
                else 
                {
                    if (IsSelfReplicatingRoot || IsChildReplica) 
                    { 
                        m_capturedContext = ec.CreateCopy();
                    } 

                    // Run the task.  We need a simple shim that converts the
                    // object back into a Task object, so that we can Execute it.
#if PFX_LEGACY_3_5 
                    ExecutionContext.Run(ec, s_ecCallback, this);
#else 
                    ExecutionContext.Run(ec, s_ecCallback, this, true); 
#endif
                } 

                Finish(true);
            }
            finally 
            {
                currentTaskSlot = previousTask; 
            } 

#if !FEATURE_PAL    // PAL doesn't support  eventing 
            // ETW event for Task Completed
            if (TplEtwProvider.Log.IsEnabled(EventLevel.Verbose, ((EventKeywords)(-1))))
            {
                // previousTask holds the actual "current task" we want to report in the event 
                if (previousTask != null)
                    TplEtwProvider.Log.TaskCompleted(previousTask.m_taskScheduler.Id, previousTask.Id, this.Id, IsFaulted); 
                else 
                    TplEtwProvider.Log.TaskCompleted(TaskScheduler.Current.Id, 0, this.Id, IsFaulted);
            } 
#endif
        }

        [SecurityCritical] 
        private static ContextCallback s_ecCallback;
 
        [SecurityCritical] 
        private static void ExecutionContextCallback(object obj)
        { 
            Task task = obj as Task;
            Contract.Assert(task != null, "expected a task object");

            task.Execute(); 

        } 
 

        ///  
        /// The actual code which invokes the body of the task. This can be overriden in derived types.
        /// 
        internal void InnerInvoke()
        { 
            Contract.Assert(m_action != null, "Null action in InnerInvoke()");
 
            Action funcA = m_action as Action; 
            if (funcA != null)
            { 
                funcA();
            }
            else
            { 
                Action funcB = m_action as Action;
                funcB(m_stateObject); 
            } 
        }
 
        /// 
        /// Alternate InnerInvoke prototype to be called from ExecuteSelfReplicating() so that
        /// the Parallel Debugger can discover the actual task being invoked.
        /// Details: Here, InnerInvoke is actually being called on the rootTask object while we are actually executing the 
        /// childTask. And the debugger needs to discover the childTask, so we pass that down as an argument.
        /// The NoOptimization and NoInlining flags ensure that the childTask pointer is retained, and that this 
        /// function appears on the callstack. 
        /// 
        ///  
        [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
        internal void InnerInvokeWithArg(Task childTask)
        {
            InnerInvoke(); 
        }
 
        ///  
        /// Performs whatever handling is necessary for an unhandled exception. Normally
        /// this just entails adding the exception to the holder object. 
        /// 
        /// The exception that went unhandled.
        private void HandleException(Exception unhandledException)
        { 
            Contract.Assert(unhandledException != null);
 
            OperationCanceledException exceptionAsOce = unhandledException as OperationCanceledException; 
            if (exceptionAsOce != null && IsCancellationRequested &&
                m_contingentProperties.m_cancellationToken == exceptionAsOce.CancellationToken) 
            {
                // All conditions are satisfied for us to go into canceled state in Finish().
                // Mark the acknowledgement, and return without adding the exception.
                // 
                // However any OCE from the task that doesn't match the tasks' own CT,
                // or that gets thrown without the CT being set will be treated as an ordinary exception and added to the aggreagate 
 
                SetCancellationAcknowledged();
            } 
            else
            {

                AddException(unhandledException); 
            }
        } 
 
        /// 
        /// Waits for the  to complete execution. 
        /// 
        /// 
        /// The  was canceled -or- an exception was thrown during
        /// the execution of the . 
        /// 
        ///  
        /// The  has been disposed. 
        /// 
        public void Wait() 
        {
#if DEBUG
            bool waitResult =
#endif 
            Wait(Timeout.Infinite, CancellationToken.None);
 
#if DEBUG 
            Contract.Assert(waitResult, "expected wait to succeed");
#endif 
        }

        /// 
        /// Waits for the  to complete execution. 
        /// 
        ///  
        /// A  that represents the number of milliseconds to wait, or a  that represents -1 milliseconds to wait indefinitely.
        ///  
        /// 
        /// true if the  completed execution within the allotted time; otherwise, false.
        /// 
        ///  
        /// The  was canceled -or- an exception was thrown during the execution of the . 
        ///  
        /// 
        ///  is a negative number other than -1 milliseconds, which represents an 
        /// infinite time-out -or- timeout is greater than
        /// .
        /// 
        ///  
        /// The  has been disposed.
        ///  
        public bool Wait(TimeSpan timeout) 
        {
            long totalMilliseconds = (long)timeout.TotalMilliseconds; 
            if (totalMilliseconds < -1 || totalMilliseconds > 0x7fffffff)
            {
                throw new ArgumentOutOfRangeException("timeout");
            } 

            return Wait((int)totalMilliseconds, CancellationToken.None); 
        } 

 
        /// 
        /// Waits for the  to complete execution.
        /// 
        ///  
        /// A  to observe while waiting for the task to complete.
        ///  
        ///  
        /// The  was canceled.
        ///  
        /// 
        /// The  was canceled -or- an exception was thrown during the execution of the .
        ///  
        /// 
        /// The  
        /// has been disposed. 
        /// 
        public void Wait(CancellationToken cancellationToken) 
        {
            Wait(Timeout.Infinite, cancellationToken);
        }
 

        ///  
        /// Waits for the  to complete execution. 
        /// 
        ///  
        /// The number of milliseconds to wait, or  (-1) to
        /// wait indefinitely.
        /// true if the  completed execution within the allotted time; otherwise,
        /// false. 
        /// 
        ///  
        ///  is a negative number other than -1, which represents an 
        /// infinite time-out.
        ///  
        /// 
        /// The  was canceled -or- an exception was thrown during the execution of the .
        ///  
        /// 
        /// The  
        /// has been disposed. 
        /// 
        public bool Wait(int millisecondsTimeout) 
        {
            return Wait(millisecondsTimeout, CancellationToken.None);
        }
 

        ///  
        /// Waits for the  to complete execution. 
        /// 
        ///  
        /// The number of milliseconds to wait, or  (-1) to
        /// wait indefinitely.
        /// 
        ///  
        /// A  to observe while waiting for the task to complete.
        ///  
        ///  
        /// true if the  completed execution within the allotted time; otherwise, false.
        ///  
        /// 
        /// The  was canceled -or- an exception was thrown during the execution of the .
        ///  
        /// 
        /// The  
        /// has been disposed. 
        /// 
        ///  
        ///  is a negative number other than -1, which represents an
        /// infinite time-out.
        /// 
        ///  
        /// The  was canceled.
        ///  
        public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) 
        {
            ThrowIfDisposed(); 

            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("millisecondsTimeout"); 
            }
 
            // Return immediately if we know that we've completed "clean" -- no exceptions, no cancellations 
            if (CompletedSuccessfully) return true;
 
            if (!InternalWait(millisecondsTimeout, cancellationToken))
                return false;

            // If an exception occurred, or the task was cancelled, throw an exception. 
            ThrowIfExceptional(true);
 
            Contract.Assert((m_stateFlags & TASK_STATE_FAULTED) == 0, "Task.Wait() completing when in Faulted state."); 

            return true; 
        }

        // Convenience method that wraps any scheduler exception in a TaskSchedulerException
        // and rethrows it. 
        private bool WrappedTryRunInline()
        { 
            if (m_taskScheduler == null) 
                return false;
 
            try
            {
                return m_taskScheduler.TryRunInline(this, true);
            } 
            catch (Exception e)
            { 
                // we 1) either received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown 
                //    2) or a a ThreadAbortException, which we need to skip here, because it would already have been handled in Task.Execute
                if (!(e is ThreadAbortException)) 
                {
                    TaskSchedulerException tse = new TaskSchedulerException(e);
                    throw tse;
                } 
                else
                { 
                    throw; 
                }
            } 
        }

        // This overload takes advantage of known values for current scheduler & statics.
        // It looks a LOT like the version above, but perf considerations prevented me 
        // from having the one above call this one.
        private bool WrappedTryRunInline(TaskScheduler currentScheduler, object currentSchedulerStatics) 
        { 
            if (m_taskScheduler == null)
                return false; 

            try
            {
                if (currentScheduler == m_taskScheduler) 
                {
                    return currentScheduler.TryRunInline(this, true, currentSchedulerStatics); 
                } 
                else
                { 
                    return m_taskScheduler.TryRunInline(this, true);
                }
            }
            catch (Exception e) 
            {
                // we 1) either received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown 
                //    2) or a a ThreadAbortException, which we need to skip here, because it would already have been handled in Task.Execute 
                if (!(e is ThreadAbortException))
                { 
                    TaskSchedulerException tse = new TaskSchedulerException(e);
                    throw tse;
                }
                else 
                {
                    throw; 
                } 
            }
        } 

        /// 
        /// The core wait function, which is only accesible internally. It's meant to be used in places in TPL code where
        /// the current context is known or cached. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        internal bool InternalWait(int millisecondsTimeout, CancellationToken cancellationToken) 
        {
#if !FEATURE_PAL    // PAL doesn't support  eventing 
            // ETW event for Task Wait Begin
            if (TplEtwProvider.Log.IsEnabled(EventLevel.Verbose, ((EventKeywords)(-1))))
            {
                Task currentTask = Task.InternalCurrent; 
                TplEtwProvider.Log.TaskWaitBegin((currentTask != null ? currentTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentTask != null ? currentTask.Id : 0),
                                                  this.Id); 
            } 
#endif
 
            bool returnValue = IsCompleted;

            // If the event hasn't already been set, we will wait.
            if (!returnValue) 
            {
                // 
                // we will attempt inline execution only if an infinite wait was requested 
                // Inline execution doesn't make sense for finite timeouts and if a cancellation token was specified
                // because we don't know how long the task delegate will take. 
                //
                TaskScheduler tm = m_taskScheduler;
                if (millisecondsTimeout == Timeout.Infinite && !cancellationToken.CanBeCanceled &&
                    WrappedTryRunInline() && IsCompleted) // TryRunInline doesn't guarantee completion, as there may be unfinished children. 
                {
                    returnValue = true; 
                } 
                else
                { 
                    returnValue = CompletedEvent.Wait(millisecondsTimeout, cancellationToken);
                }
            }
 
            Contract.Assert(IsCompleted || millisecondsTimeout != Timeout.Infinite);
 
#if !FEATURE_PAL    // PAL doesn't support  eventing 
            // ETW event for Task Wait End
            if (TplEtwProvider.Log.IsEnabled(EventLevel.Verbose, ((EventKeywords)(-1)))) 
            {
                Task currentTask = Task.InternalCurrent;
                TplEtwProvider.Log.TaskWaitEnd((currentTask != null ? currentTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentTask != null ? currentTask.Id : 0),
                                                  this.Id); 
            }
#endif 
 
            return returnValue;
        } 


        /// 
        /// Cancels the . 
        /// 
        ///  Indiactes whether we should only cancel non-invoked tasks. 
        /// For the default scheduler this option will only be serviced through TryDequeue. 
        /// For custom schedulers we also attempt an atomic state transition.
        /// true if the task was successfully canceled; otherwise, false. 
        /// The 
        /// has been disposed.
        [SecuritySafeCritical]
        internal bool InternalCancel(bool bCancelNonExecutingOnly) 
        {
            Contract.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) == 0, "Task.InternalCancel() did not expect promise-style task"); 
            ThrowIfDisposed(); 

            bool bPopSucceeded = false; 
            bool mustCleanup = false;

            TaskSchedulerException tse = null;
 
            // If started, and running in a task context, we can try to pop the chore.
            if ((m_stateFlags & TASK_STATE_STARTED) != 0) 
            { 
                TaskScheduler ts = m_taskScheduler;
 
                try
                {
                    bPopSucceeded = (ts != null) && ts.TryDequeue(this);
                } 
                catch (Exception e)
                { 
                    // TryDequeue threw. We don't know whether the task was properly dequeued or not. So we must let the rest of 
                    // the cancellation logic run its course (record the request, attempt atomic state transition and do cleanup where appropriate)
                    // Here we will only record a TaskSchedulerException, which will later be thrown at function exit. 

                    if (!(e is ThreadAbortException))
                    {
                        tse = new TaskSchedulerException(e); 
                    }
                } 
 
                bool bRequiresAtomicStartTransition = ( ts != null && ts.RequiresAtomicStartTransition) || ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0);
 
                if (!bPopSucceeded && bCancelNonExecutingOnly && bRequiresAtomicStartTransition)
                {
                    // The caller requested cancellation of non-invoked tasks only, and TryDequeue was one way of doing it...
                    // Since that seems to have failed, we should now try an atomic state transition (from non-invoked state to canceled) 
                    // An atomic transition here is only safe if we know we're on a custom task scheduler, which also forces a CAS on ExecuteEntry
 
                    // Even though this task can't have any children, we should be ready for handling any continuations that 
                    // may be attached to it (although currently
                    // So we need to remeber whether we actually did the flip, so we can do clean up (finish continuations etc) 
                    mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED, TASK_STATE_DELEGATE_INVOKED | TASK_STATE_CANCELED);


                    // PS: This is slightly different from the regular cancellation codepath 
                    // since we record the cancellation request *after* doing the state transition.
                    // However that shouldn't matter too much because the task was never invoked, thus can't have children 
                } 

            } 

            if (!bCancelNonExecutingOnly || bPopSucceeded || mustCleanup)
            {
                // Record the cancellation request. 
                RecordInternalCancellationRequest();
 
                // Determine whether we need to clean up 
                // This will be the case
                //     1) if we were able to pop, and we win the ---- to update task state to TASK_STATE_CANCELED 
                //     2) if the task seems to be yet unstarted, and we win the ---- to transition to
                //        TASK_STATE_CANCELED before anyone else can transition into _STARTED or _CANCELED or
                //        _RAN_TO_COMPLETION or _FAULTED
                // Note that we do not check for TASK_STATE_COMPLETION_RESERVED.  That only applies to promise-style 
                // tasks, and a promise-style task should not enter into this codepath.
                if (bPopSucceeded) 
                { 
                    // hitting this would mean something wrong with the AtomicStateUpdate above
                    Contract.Assert(!mustCleanup, "Possibly an invalid state transition call was made in InternalCancel()"); 

                    // Include TASK_STATE_DELEGATE_INVOKED in "illegal" bits to protect against the situation where
                    // TS.TryDequeue() returns true but the task is still left on the queue.
                    mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED, TASK_STATE_CANCELED | TASK_STATE_DELEGATE_INVOKED); 
                }
                else if (!mustCleanup && (m_stateFlags & TASK_STATE_STARTED) == 0) 
                { 
                    mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED,
                        TASK_STATE_CANCELED | TASK_STATE_STARTED | TASK_STATE_RAN_TO_COMPLETION | 
                        TASK_STATE_FAULTED | TASK_STATE_DELEGATE_INVOKED);
                }

                // do the cleanup (i.e. set completion event and finish continuations) 
                if (mustCleanup)
                { 
                    CancellationCleanupLogic(); 
                }
            } 

            if (tse != null)
                throw tse;
            else 
                return (mustCleanup);
        } 
 
        // Breaks out logic for recording a cancellation request
        internal void RecordInternalCancellationRequest() 
        {
            // Record the cancellation request.
            LazyInitializer.EnsureInitialized(ref m_contingentProperties, s_contingentPropertyCreator);
 
            m_contingentProperties.m_internalCancellationRequested = CANCELLATION_REQUESTED;
 
        } 

        // ASSUMES THAT A SUCCESSFUL CANCELLATION HAS JUST OCCURRED ON THIS TASK!!! 
        // And this method should be called at most once per task.
        internal void CancellationCleanupLogic()
        {
            Contract.Assert((m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_COMPLETION_RESERVED)) != 0, "Task.CancellationCleanupLogic(): Task not canceled or reserved."); 
            // I'd like to do this, but there is a small window for a race condition.  If someone calls Wait() between InternalCancel() and
            // here, that will set m_completionEvent, leading to a meaningless/harmless assertion. 
            //Contract.Assert((m_completionEvent == null) || !m_completionEvent.IsSet, "Task.CancellationCleanupLogic(): Completion event already set."); 

            // This may have been set already, but we need to make sure. 
            Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_CANCELED);

            // Fire completion event if it has been lazily initialized
            SetCompleted(); 

            // Notify parents, fire continuations, other cleanup. 
            FinishStageThree(); 
        }
 

        /// 
        /// Sets the task's cancellation acknowledged flag.
        ///  
        private void SetCancellationAcknowledged()
        { 
            Contract.Assert(this == Task.InternalCurrent, "SetCancellationAcknowledged() should only be called while this is still the current task"); 
            Contract.Assert(IsCancellationRequested, "SetCancellationAcknowledged() should not be called if the task's CT wasn't signaled");
 
            m_stateFlags |= TASK_STATE_CANCELLATIONACKNOWLEDGED;
        }

 
        //
        // Continuation passing functionality (aka ContinueWith) 
        // 

        ///  
        /// A structure to hold continuation information.
        /// 
        internal struct TaskContinuation
        { 
            internal object m_task; // The delegate OR unstarted continuation task.
            internal TaskScheduler m_taskScheduler; // The TaskScheduler with which to associate the continuation task. 
            internal TaskContinuationOptions m_options; // What kind of continuation. 

            ///  
            /// Constructs a new continuation structure.
            /// 
            /// The task to be activated.
            /// The continuation options. 
            /// The scheduler to use for the continuation.
            internal TaskContinuation(Task task, TaskScheduler scheduler, TaskContinuationOptions options) 
            { 
                Contract.Assert(task != null, "TaskContinuation ctor: task is null");
 
                m_task = task;
                m_taskScheduler = scheduler;
                m_options = options;
            } 

            internal TaskContinuation(Action action) 
            { 
                m_task = action;
                m_taskScheduler = null; 
                m_options = TaskContinuationOptions.None;
            }

            ///  
            /// Invokes the continuation for the target completion task.
            ///  
            /// The completed task. 
            /// Whether the continuation can be inlined.
            [SecuritySafeCritical] // Needed for QueueTask 
            internal void Run(Task completedTask, bool bCanInlineContinuationTask)
            {
                Contract.Assert(completedTask.IsCompleted, "ContinuationTask.Run(): completedTask not completed");
 
                Task task = m_task as Task;
                if (task != null) 
                { 
                    if (completedTask.ContinueWithIsRightKind(m_options))
                    { 
                        task.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 && (m_options & TaskContinuationOptions.ExecuteSynchronously) != 0)
                        { 
                            // Execute() won't set the TASK_STATE_STARTED flag, so we'll do it here. 
                            if (!task.MarkStarted())
                            { 
                                // task has been canceled.  Abort this continuation thread.
                                return;
                            }
 
                            try
                            { 
                                if (!m_taskScheduler.TryRunInline(task, false)) 
                                {
                                    m_taskScheduler.QueueTask(task); 
                                }
                            }
                            catch (Exception e)
                            { 
                                // Either TryRunInline() or QueueTask() threw an exception. Record the exception, marking the task as Faulted.
                                // However if it was a ThreadAbortException coming from TryRunInline we need to skip here, 
                                // because it would already have been handled in Task.Execute() 
                                if (!(e is ThreadAbortException &&
                                      (task.m_stateFlags & TASK_STATE_THREAD_WAS_ABORTED) != 0))    // this ensures TAEs from QueueTask will be wrapped in TSE 
                                {
                                    TaskSchedulerException tse = new TaskSchedulerException(e);
                                    task.AddException(tse);
                                    task.Finish(false); 
                                }
 
                                // Don't re-throw. 
                            }
                        } 
                        else
                        {
                            try
                            { 
                                task.ScheduleAndStart(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.
                            }
                        } 
                    }
                    else 
                    { 
                        // The final state of this task does not match the desired
                        // continuation activation criteria; cancel it to denote this. 
                        task.InternalCancel(false);
                    }
                }
                else 
                {
                    // Note for the future: ContinuationAction still run synchronously regardless of ThreadAbortException handling. 
                    // This is probably not too importnat right now, because the internal use of continuationActions only involve short actions. 
                    // However if we ever make these public, we need to turn them into tasks if the antecedent threw a ThreadAbortException.
                    Action action = m_task as Action; 
                    Contract.Assert(action != null, "TaskContinuation.Run(): Unknown m_task type.");
                    action(completedTask);
                }
            } 
        }
 
        ///  
        /// Runs all of the continuations, as appropriate.
        ///  
        private void FinishContinuations()
        {
            // Grab the list of continuations, and lock it to contend with concurrent adds.
            // At this point, IsCompleted == true, so those adding will either come before 
            // that and add a continuation under the lock (serializing before this), so we
            // will run it; or they will attempt to acquire the lock, get it, and then see the 
            // task is completed (serializing after this), and run it on their own. 
            List continuations = (m_contingentProperties == null) ? null : m_contingentProperties.m_continuations;
            if (continuations != null) 
            {
                lock (m_contingentProperties)
                {
                    // Ensure that all concurrent adds have completed. 
                }
 
                // skip synchronous execution of continuations if this tasks thread was aborted 
                bool bCanInlineContinuations = !(((m_stateFlags & TASK_STATE_THREAD_WAS_ABORTED) != 0) ||
                                                  (Thread.CurrentThread.ThreadState == ThreadState.AbortRequested)); 

                // Records earliest index of synchronous continuation.
                // A value of -1 means that no synchronous continuations were found.
                int firstSynchronousContinuation = -1; 

                // Fire the asynchronous continuations first ... 
                // Go back-to-front to make the "firstSynchronousContinuation" logic simpler. 
                for (int i = continuations.Count - 1; i >= 0; i--)
                { 
                    TaskContinuation tc = continuations[i];
                    // ContinuationActions, which execute synchronously, have a null scheduler
                    // Synchronous continuation tasks will have the ExecuteSynchronously option
                    if ((tc.m_taskScheduler != null) && ((tc.m_options & TaskContinuationOptions.ExecuteSynchronously) == 0)) 
                    {
                        tc.Run(this, bCanInlineContinuations); 
                    } 
                    else firstSynchronousContinuation = i;
                } 

                // ... and then fire the synchronous continuations (if there are any)
                if (firstSynchronousContinuation > -1)
                { 
                    for (int i = firstSynchronousContinuation; i < continuations.Count; i++)
                    { 
                        TaskContinuation tc = continuations[i]; 
                        // ContinuationActions, which execute synchronously, have a null scheduler
                        // Synchronous continuation tasks will have the ExecuteSynchronously option 
                        if ((tc.m_taskScheduler == null) || ((tc.m_options & TaskContinuationOptions.ExecuteSynchronously) != 0))
                            tc.Run(this, bCanInlineContinuations);
                    }
                } 

                // Don't keep references to "spent" continuations 
                m_contingentProperties.m_continuations = null; 
            }
        } 

        /// 
        /// Helper function to determine whether the current task is in the state desired by the
        /// continuation kind under evaluation. Three possibilities exist: the task failed with 
        /// an unhandled exception (OnFailed), the task was canceled before running (OnAborted),
        /// or the task completed successfully (OnCompletedSuccessfully).  Note that the last 
        /// one includes completing due to cancellation. 
        /// 
        /// The continuation options under evaluation. 
        /// True if the continuation should be run given the task's current state.
        internal bool ContinueWithIsRightKind(TaskContinuationOptions options)
        {
            Contract.Assert(IsCompleted); 

            if (IsFaulted) 
            { 
                return (options & TaskContinuationOptions.NotOnFaulted) == 0;
            } 
            else if (IsCanceled)
            {
                return (options & TaskContinuationOptions.NotOnCanceled) == 0;
            } 
            else
            { 
                return (options & TaskContinuationOptions.NotOnRanToCompletion) == 0; 
            }
        } 

        /// 
        /// 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. 
        /// 
        ///  
        /// 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  that will be assigned to the new continuation task. 
        /// 
        /// 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, just with a stack mark parameter. 
        private Task ContinueWith(Action continuationAction, TaskScheduler scheduler, 
            CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
        { 
            ThrowIfDisposed();

            // Throw on continuation with null action
            if (continuationAction == null) 
            {
                throw new ArgumentNullException("continuationAction"); 
            } 

            // Throw on continuation with null TaskScheduler 
            if (scheduler == null)
            {
                throw new ArgumentNullException("scheduler");
            } 

            TaskCreationOptions creationOptions; 
            InternalTaskOptions internalOptions; 
            CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
 
            Task thisTask = this;
            Task continuationTask = new Task(
                delegate(object obj) { continuationAction(thisTask); },
                null, 
                Task.InternalCurrent,
                cancellationToken, 
                creationOptions, 
                internalOptions,
                null, // leave taskScheduler 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 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 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(Func 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 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. 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(Func 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 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(Func 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 parameter.
        private Task ContinueWith(Func continuationFunction, TaskScheduler scheduler, 
            CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark) 
        {
            ThrowIfDisposed(); 

            // Throw on continuation with null function
            if (continuationFunction == null)
            { 
                throw new ArgumentNullException("continuationFunction");
            } 
 
            // Throw on continuation with null task scheduler
            if (scheduler == null) 
            {
                throw new ArgumentNullException("scheduler");
            }
 
            TaskCreationOptions creationOptions;
            InternalTaskOptions internalOptions; 
            CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions); 

            Task thisTask = this; 
            Task continuationTask = new Task(
                delegate() { return continuationFunction(thisTask); },
                Task.InternalCurrent,
                cancellationToken, 
                creationOptions,
                internalOptions, 
                null, // leave taskScheduler 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; 
        } 

        ///  
        /// Converts TaskContinuationOptions to TaskCreationOptions, and also does
        /// some validity checking along the way.
        /// 
        /// Incoming TaskContinuationOptions 
        /// Outgoing TaskCreationOptions
        /// Outgoing InternalTaskOptions 
        internal static void CreationOptionsFromContinuationOptions( 
            TaskContinuationOptions continuationOptions,
            out TaskCreationOptions creationOptions, 
            out InternalTaskOptions internalOptions)
        {
            // This is used a couple of times below
            TaskContinuationOptions NotOnAnything = 
                TaskContinuationOptions.NotOnCanceled |
                TaskContinuationOptions.NotOnFaulted | 
                TaskContinuationOptions.NotOnRanToCompletion; 

            TaskContinuationOptions creationOptionsMask = 
                TaskContinuationOptions.PreferFairness |
                TaskContinuationOptions.LongRunning |
                TaskContinuationOptions.AttachedToParent;
 

            // Check that LongRunning and ExecuteSynchronously are not specified together 
            TaskContinuationOptions illegalMask = TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.LongRunning; 
            if ((continuationOptions & illegalMask) == illegalMask)
            { 
                throw new ArgumentOutOfRangeException("continuationOptions", Environment.GetResourceString("Task_ContinueWith_ESandLR"));
            }

            // Check that no illegal options were specified 
            if ((continuationOptions &
                ~(creationOptionsMask | NotOnAnything | 
                  TaskContinuationOptions.ExecuteSynchronously)) != 0) 
            {
                throw new ArgumentOutOfRangeException("continuationOptions"); 
            }

            // Check that we didn't specify "not on anything"
            if ((continuationOptions & NotOnAnything) == NotOnAnything) 
            {
                throw new ArgumentOutOfRangeException("continuationOptions", Environment.GetResourceString("Task_ContinueWith_NotOnAnything")); 
            } 

            creationOptions = (TaskCreationOptions)(continuationOptions & creationOptionsMask); 
            internalOptions = InternalTaskOptions.ContinuationTask;
        }

 
        /// 
        /// Registers the continuation and possibly runs it (if the task is already finished). 
        ///  
        /// The continuation task itself.
        /// TaskScheduler with which to associate continuation task. 
        /// Restrictions on when the continuation becomes active.
        internal void ContinueWithCore(Task continuationTask, TaskScheduler scheduler, TaskContinuationOptions options)
        {
            Contract.Assert(continuationTask != null, "Task.ContinueWithCore(): null continuationTask"); 
            Contract.Assert((!continuationTask.IsCompleted) || continuationTask.CancellationToken.IsCancellationRequested,
                "Task.ContinueWithCore(): continuationTask is completed and its CT is not signaled"); 
 
            // It doesn't really do any harm to queue up an already-completed continuation, but it's
            // a little wasteful.  So we'll make an attempt at avoiding it (although the race condition 
            // here could still result in a completed continuation task being queued.)
            if (continuationTask.IsCompleted) return;

            TaskContinuation continuation = new TaskContinuation(continuationTask, scheduler, options); 

            // If the task has not finished, we will enqueue the continuation to fire when completed. 
            if (!IsCompleted) 
            {
                // If not created yet, we will atomically initialize the queue of actions. 
                LazyInitializer.EnsureInitialized(ref m_contingentProperties, s_contingentPropertyCreator);
                if (m_contingentProperties.m_continuations == null)
                {
                    Interlocked.CompareExchange(ref m_contingentProperties.m_continuations, new List(), null); 
                }
 
                // Now we must serialize access to the list itself. 
                lock (m_contingentProperties)
                { 
                    // We have to check IsCompleted again here, since the task may have
                    // finished before we got around to acquiring the lock on the actions.
                    // There is a race condition here, but it's OK.  If the thread that
                    // finishes the task notices a non-null actions queue it will try to 
                    // acquire a lock on it.  Thus it will have to wait for the current
                    // thread to exit the critical region we're currently in. 
                    if (!IsCompleted) 
                    {
                        m_contingentProperties.m_continuations.Add(continuation); 
                        return;
                    }
                }
            } 

            // If we fell through, the task has already completed.  We'll invoke the action inline. 
            // Only start the continuation if the right kind was established. 
            continuation.Run(this, true);
        } 

        // Adds a lightweight completion action to a task.  This is similar to a continuation
        // task except that it is stored as an action, and thus does not require the allocation/
        // execution resources of a continuation task. 
        //
        // Used internally by ContinueWhenAll() and ContinueWhenAny(). 
        internal void AddCompletionAction(Action action) 
        {
            if (!IsCompleted) 
            {
                LazyInitializer.EnsureInitialized(ref m_contingentProperties, s_contingentPropertyCreator);
                TaskContinuation tc = new TaskContinuation(action);
                if (m_contingentProperties.m_continuations == null) 
                {
                    Interlocked.CompareExchange(ref m_contingentProperties.m_continuations, new List(), null); 
                } 

                // Serialize access to the continuations list 
                lock (m_contingentProperties)
                {
                    // We have to check IsCompleted again here, since the task may have
                    // finished before we got around to acquiring the lock on the actions. 
                    // There is a race condition here, but it's OK.  If the thread that
                    // finishes the task notices a non-null actions queue it will try to 
                    // acquire a lock on it.  Thus it will have to wait for the current 
                    // thread to exit the critical region we're currently in.
                    if (!IsCompleted) 
                    {
                        m_contingentProperties.m_continuations.Add(tc);
                        return;
                    } 
                }
            } 
 
            // If we got this far, we've already completed
            action(this); 
        }


        // 
        // Wait methods
        // 
 
        /// 
        /// Waits for all of the provided  objects to complete execution. 
        /// 
        /// 
        /// An array of  instances on which to wait.
        ///  
        /// 
        /// The  argument is null. 
        ///  
        /// 
        /// The  argument contains a null element. 
        /// 
        /// 
        /// At least one of the  instances was canceled -or- an exception was thrown during
        /// the execution of at least one of the  instances. 
        /// 
        ///  
        /// The  has been disposed. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static void WaitAll(params Task[] tasks)
        {
#if DEBUG
            bool waitResult = 
#endif
            WaitAll(tasks, Timeout.Infinite); 
 
#if DEBUG
            Contract.Assert(waitResult, "expected wait to succeed"); 
#endif
        }

        ///  
        /// Waits for all of the provided  objects to complete execution.
        ///  
        ///  
        /// true if all of the  instances completed execution within the allotted time;
        /// otherwise, false. 
        /// 
        /// 
        /// An array of  instances on which to wait.
        ///  
        /// 
        /// A  that represents the number of milliseconds to wait, or a  that represents -1 milliseconds to wait indefinitely. 
        /// 
        ///  
        /// The  argument is null.
        /// 
        /// 
        /// The  argument contains a null element. 
        /// 
        ///  
        /// At least one of the  instances was canceled -or- an exception was thrown during 
        /// the execution of at least one of the  instances.
        ///  
        /// 
        ///  is a negative number other than -1 milliseconds, which represents an
        /// infinite time-out -or- timeout is greater than
        /// . 
        /// 
        ///  
        /// The  has been disposed. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static bool WaitAll(Task[] tasks, TimeSpan timeout)
        {
            long totalMilliseconds = (long)timeout.TotalMilliseconds;
            if (totalMilliseconds < -1 || totalMilliseconds > 0x7fffffff) 
            {
                throw new ArgumentOutOfRangeException("timeout"); 
            } 

            return WaitAll(tasks, (int)totalMilliseconds); 

        }

        ///  
        /// Waits for all of the provided  objects to complete execution.
        ///  
        ///  
        /// true if all of the  instances completed execution within the allotted time;
        /// otherwise, false. 
        /// 
        /// 
        /// The number of milliseconds to wait, or  (-1) to
        /// wait indefinitely. 
        /// An array of  instances on which to wait.
        ///  
        ///  
        /// The  argument is null.
        ///  
        /// 
        /// The  argument contains a null element.
        /// 
        ///  
        /// At least one of the  instances was canceled -or- an exception was thrown during
        /// the execution of at least one of the  instances. 
        ///  
        /// 
        /// The  has been disposed. 
        /// 
        /// 
        ///  is a negative number other than -1, which represents an
        /// infinite time-out. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static bool WaitAll(Task[] tasks, int millisecondsTimeout) 
        {
            return WaitAll(tasks, millisecondsTimeout, CancellationToken.None); 
        }

        /// 
        /// Waits for all of the provided  objects to complete execution. 
        /// 
        ///  
        /// true if all of the  instances completed execution within the allotted time; 
        /// otherwise, false.
        ///  
        /// 
        /// An array of  instances on which to wait.
        /// 
        ///  
        /// A  to observe while waiting for the tasks to complete.
        ///  
        ///  
        /// The  argument is null.
        ///  
        /// 
        /// The  argument contains a null element.
        /// 
        ///  
        /// At least one of the  instances was canceled -or- an exception was thrown during
        /// the execution of at least one of the  instances. 
        ///  
        /// 
        /// The  was canceled. 
        /// 
        /// 
        /// The  has been disposed.
        ///  
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
        public static void WaitAll(Task[] tasks, CancellationToken cancellationToken) 
        { 
            WaitAll(tasks, Timeout.Infinite, cancellationToken);
        } 

        /// 
        /// Waits for all of the provided  objects to complete execution.
        ///  
        /// 
        /// true if all of the  instances completed execution within the allotted time; 
        /// otherwise, false. 
        /// 
        ///  
        /// An array of  instances on which to wait.
        /// 
        /// 
        /// The number of milliseconds to wait, or  (-1) to 
        /// wait indefinitely.
        ///  
        ///  
        /// A  to observe while waiting for the tasks to complete.
        ///  
        /// 
        /// The  argument is null.
        /// 
        ///  
        /// The  argument contains a null element.
        ///  
        ///  
        /// At least one of the  instances was canceled -or- an exception was thrown during
        /// the execution of at least one of the  instances. 
        /// 
        /// 
        /// The  has been disposed.
        ///  
        /// 
        ///  is a negative number other than -1, which represents an 
        /// infinite time-out. 
        /// 
        ///  
        /// The  was canceled.
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
        public static bool WaitAll(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken) 
        {
            if (tasks == null) 
            { 
                throw new ArgumentNullException("tasks");
            } 
            if (millisecondsTimeout < -1)
            {
                throw new ArgumentOutOfRangeException("timeout");
            } 

#if DEBUG 
            Contract.Assert(tasks != null && millisecondsTimeout >= -1, "invalid arguments passed to WaitAll"); 
#endif
            cancellationToken.ThrowIfCancellationRequested(); // early check before we make any allocations 

            //
            // In this WaitAll() implementation we have 2 alternate code paths for a task to be handled:
            // CODEPATH1: skip an already completed task, CODEPATH2: actually wait on task's handle 
            // We make sure that the exception behavior of Task.Wait() is replicated the same for tasks handled in either of these codepaths
            // 
 
            List exceptions = null;
            List waitedOnTaskList = null; // tasks whose async handles we actually grabbed 

            bool returnValue = true;
            Task currentTask = Task.InternalCurrent;
            TaskScheduler currentTm = (currentTask == null) ? TaskScheduler.Default : currentTask.ExecutingTaskScheduler; 
            object currentTmStatics = currentTm.GetThreadStatics();
 
            // Collects incomplete tasks in "waitedOnTaskList" 
            for (int i = tasks.Length - 1; i >= 0; i--)
            { 
                Task task = tasks[i];

                if (task == null)
                { 
                    throw new ArgumentException(Environment.GetResourceString("Task_WaitMulti_NullTask"), "tasks");
                } 
 
                task.ThrowIfDisposed();
 
                bool taskIsCompleted = task.IsCompleted;
                if (!taskIsCompleted)
                {
                    // try inlining the task only if we have an infinite timeout and an empty cancellation token 
                    if (millisecondsTimeout != Timeout.Infinite || cancellationToken.CanBeCanceled)
                    { 
                        // We either didn't attempt inline execution because we had a non-infinite timeout or we had a cancellable token. 
                        // In all cases we need to do a full wait on the task (=> add its event into the list.)
                        if (waitedOnTaskList == null) 
                        {
                            waitedOnTaskList = new List(tasks.Length);
                        }
                        waitedOnTaskList.Add(task); 
                    }
                    else 
                    { 
                        // We are eligible for inlining.
                        taskIsCompleted = task.WrappedTryRunInline(currentTm, currentTmStatics) && 
                            task.IsCompleted; // A successful TryRunInline doesn't guarantee completion

                        if (!taskIsCompleted)
                        { 
                            // Inlining didn't work.
                            // Do a full wait on the task (=> add its event into the list.) 
                            if (waitedOnTaskList == null) 
                            {
                                waitedOnTaskList = new List(tasks.Length); 
                            }
                            waitedOnTaskList.Add(task);

                        } 
                    }
                } 
 
                if (taskIsCompleted)
                { 
                    // The task has finished. Make sure we aggregate its exceptions.
                    AddExceptionsForCompletedTask(ref exceptions, task);

                } 
            }
 
            if (waitedOnTaskList != null) 
            {
                Contract.Assert(waitedOnTaskList.Count > 0); 
                WaitHandle[] waitHandles = new WaitHandle[waitedOnTaskList.Count];
                for (int i = 0; i < waitHandles.Length; i++)
                {
                    waitHandles[i] = waitedOnTaskList[i].CompletedEvent.WaitHandle; 
                }
                returnValue = WaitAllSTAAnd64Aware(waitHandles, millisecondsTimeout, cancellationToken); 
 
                // If the wait didn't time out, ensure exceptions are propagated.
                if (returnValue) 
                {
                    for (int i = 0; i < waitedOnTaskList.Count; i++)
                    {
                        AddExceptionsForCompletedTask(ref exceptions, waitedOnTaskList[i]); 
                    }
                } 
 
                // We need to prevent the tasks array from being GC'ed until we come out of the wait.
                // This is necessary so that the Parallel Debugger can traverse it during the long wait and deduce waiter/waitee relationships 
                GC.KeepAlive(tasks);
            }

            // If one or more threw exceptions, aggregate them. 
            if (exceptions != null)
            { 
                throw new AggregateException(exceptions); 
            }
 
            return returnValue;
        }

        ///  
        /// Waits for a set of handles in a STA-aware way.  In other words, it will wait for each
        /// of the events individually if we're on a STA thread, because MsgWaitForMultipleObjectsEx 
        /// can't do a true wait-all due to its hidden message queue event. This is not atomic, 
        /// of course, but we only wait on one-way (MRE) events anyway so this is OK.
        ///  
        /// An array of wait handles to wait on.
        /// The timeout to use during waits.
        /// The cancellationToken that enables a wait to be canceled.
        /// True if all waits succeeded, false if a timeout occurred. 
        private static bool WaitAllSTAAnd64Aware(WaitHandle[] waitHandles, int millisecondsTimeout, CancellationToken cancellationToken)
        { 
            const int MAX_WAIT_HANDLES = 64; 

            if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA 
                || cancellationToken.CanBeCanceled)
            {
                // We're on an STA thread, so we can't use the real Win32 wait-all.
                // We instead walk the list, and wait on each individually.  Perf will 
                // be poor because we'll incur O(N) context switches as we wake up.
 
                // CancellationToken enabled waits will also choose this codepath regardless of apartment state. 
                // The ability to use WaitAny to probe for cancellation during one by one waits makes it easy to support CT without introducing racy code paths.
 
                WaitHandle[] cancelableWHPair = null; // to be used with WaitAny if we have a CancellationToken

                if (cancellationToken.CanBeCanceled)
                { 
                    cancelableWHPair = new WaitHandle[2]; // one for the actual wait handle, other for the cancellation event
                    cancelableWHPair[1] = cancellationToken.WaitHandle; 
                } 

                for (int i = 0; i < waitHandles.Length; i++) 
                {
                    long startTicks = (millisecondsTimeout == Timeout.Infinite) ? 0 : DateTime.UtcNow.Ticks;

                    if (cancellationToken.CanBeCanceled) 
                    {
                        // do a WaitAny on the WH of interest and the cancellation event. 
                        cancelableWHPair[0] = waitHandles[i]; 
                        int waitRetCode = WaitHandle.WaitAny(cancelableWHPair, millisecondsTimeout, false);
                        if (waitRetCode == WaitHandle.WaitTimeout) 
                            return false;

                        // we could have come out of the wait due to index 1 (i.e. cancellationToken.WaitHandle), check and throw
                        cancellationToken.ThrowIfCancellationRequested(); 

                        // the wait should have returned 0, otherwise we have a bug in CT or the code above 
                        Contract.Assert(waitRetCode == 0, "Unexpected waitcode from WaitAny with cancellation event"); 
                    }
                    else 
                    {

                        if (!waitHandles[i].WaitOne(millisecondsTimeout, false))
                            return false; 
                    }
 
 
                    // Adjust the timeout.
                    if (millisecondsTimeout != Timeout.Infinite) 
                    {
                        long elapsedMilliseconds = (DateTime.UtcNow.Ticks - startTicks) / TimeSpan.TicksPerMillisecond;
                        if (elapsedMilliseconds > int.MaxValue || elapsedMilliseconds > millisecondsTimeout)
                            return false; 
                        millisecondsTimeout -= (int)elapsedMilliseconds;
                    } 
                } 
            }
            else if (waitHandles.Length <= MAX_WAIT_HANDLES) 
            {
                // We aren't on an STA thread, and have fewer than the Win32 limit.
                // Just issue a true wait-all wait.
 
                Contract.Assert(!cancellationToken.CanBeCanceled);
 
                if (!WaitHandle.WaitAll(waitHandles, millisecondsTimeout, false)) 
                    return false;
            } 
            else
            {
                // Otherwise, we need to chunk the handles into groups of the Win32 limit.
 
                Contract.Assert(!cancellationToken.CanBeCanceled);
 
                int chunks = (waitHandles.Length + MAX_WAIT_HANDLES - 1) / MAX_WAIT_HANDLES; 
                WaitHandle[] waitHandlesChunk = new WaitHandle[MAX_WAIT_HANDLES];
                long startTicks = (millisecondsTimeout == Timeout.Infinite) ? 0 : DateTime.UtcNow.Ticks; 

                for (int i = 0; i < chunks; i++)
                {
                    if (i == chunks - 1 && (waitHandles.Length % MAX_WAIT_HANDLES) != 0) 
                    {
                        // We're on the last chunk, and it's not evenly sized.  We need to 
                        // allocate an array of WaitHandles that is perfectly sized.  This is 
                        // because the WaitAll API doesn't allow null entries.
                        waitHandlesChunk = new WaitHandle[waitHandles.Length % MAX_WAIT_HANDLES]; 
                    }

                    Array.Copy(waitHandles, i * MAX_WAIT_HANDLES, waitHandlesChunk, 0, waitHandlesChunk.Length);
 
                    if (!WaitHandle.WaitAll(waitHandlesChunk, millisecondsTimeout, false))
                        return false; 
 
                    // Adjust the timeout.
                    if (millisecondsTimeout != Timeout.Infinite) 
                    {
                        long elapsedMilliseconds = (DateTime.UtcNow.Ticks - startTicks) / TimeSpan.TicksPerMillisecond;
                        if (elapsedMilliseconds > int.MaxValue || elapsedMilliseconds > millisecondsTimeout)
                            return false; 
                        millisecondsTimeout -= (int)elapsedMilliseconds;
                    } 
                } 
            }
 
            return true;
        }

        ///  
        /// Internal WaitAll implementation which is meant to be used with small number of tasks,
        /// optimized for Parallel.Invoke and other structured primitives. 
        ///  
        internal static void FastWaitAll(Task[] tasks)
        { 
#if DEBUG
            Contract.Assert(tasks != null);
#endif
 
            List exceptions = null;
            TaskScheduler currentTm = TaskScheduler.Current; 
            object currentTmStatics = currentTm.GetThreadStatics(); 

            // Collects incomplete tasks in "waitedOnTaskList" and their cooperative events in "cooperativeEventList" 
            for (int i = tasks.Length - 1; i >= 0; i--)
            {
                if (!tasks[i].IsCompleted)
                { 
                    // Just attempting to inline here... result doesn't matter.
                    // We'll do a second pass to do actual wait on each task, and to aggregate their exceptions. 
                    // If the task is inlined here, it will register as IsCompleted in the second pass 
                    // and will just give us the exception.
 
                    tasks[i].WrappedTryRunInline(currentTm, currentTmStatics);
                }
            }
 
            // Wait on the tasks.
            for (int i = tasks.Length - 1; i >= 0; i--) 
            { 
                tasks[i].CompletedEvent.Wait(); // Just a boolean check if the task is already done.
                AddExceptionsForCompletedTask(ref exceptions, tasks[i]); 
            }

            // If one or more threw exceptions, aggregate them.
            if (exceptions != null) 
            {
                throw new AggregateException(exceptions); 
            } 
        }
 
        /// 
        /// This internal function is only meant to be called by WaitAll()
        /// If the completed task is canceled or it has other exceptions, here we will add those
        /// into the passed in exception list (which will be lazily initialized here). 
        /// 
        internal static void AddExceptionsForCompletedTask(ref List exceptions, Task t) 
        { 
            AggregateException ex = t.GetExceptions(true);
            if (ex != null) 
            {
                // make sure the task's exception observed status is set appropriately
                // it's possible that WaitAll was called by the parent of an attached child,
                // this will make sure it won't throw again in the implicit wait 
                t.UpdateExceptionObservedStatus();
 
                if (exceptions == null) 
                {
                    exceptions = new List(ex.InnerExceptions.Count); 
                }

                exceptions.AddRange(ex.InnerExceptions);
            } 
        }
 
 
        /// 
        /// Waits for any of the provided  objects to complete execution. 
        /// 
        /// 
        /// An array of  instances on which to wait.
        ///  
        /// The index of the completed task in the  array argument.
        ///  
        /// The  argument is null. 
        /// 
        ///  
        /// The  argument contains a null element.
        /// 
        /// 
        /// The  has been disposed. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static int WaitAny(params Task[] tasks) 
        {
            int waitResult = WaitAny(tasks, Timeout.Infinite); 
            Contract.Assert(tasks.Length == 0 || waitResult != -1, "expected wait to succeed");
            return waitResult;
        }
 
        /// 
        /// Waits for any of the provided  objects to complete execution. 
        ///  
        /// 
        /// An array of  instances on which to wait. 
        /// 
        /// 
        /// A  that represents the number of milliseconds to wait, or a  that represents -1 milliseconds to wait indefinitely. 
        /// 
        ///  
        /// The index of the completed task in the  array argument, or -1 if the 
        /// timeout occurred.
        ///  
        /// 
        /// The  argument is null.
        /// 
        ///  
        /// The  argument contains a null element.
        ///  
        ///  
        /// The  has been disposed.
        ///  
        /// 
        ///  is a negative number other than -1 milliseconds, which represents an
        /// infinite time-out -or- timeout is greater than
        /// . 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static int WaitAny(Task[] tasks, TimeSpan timeout) 
        {
            long totalMilliseconds = (long)timeout.TotalMilliseconds; 
            if (totalMilliseconds < -1 || totalMilliseconds > 0x7fffffff)
            {
                throw new ArgumentOutOfRangeException("timeout");
            } 

            return WaitAny(tasks, (int)totalMilliseconds); 
        } 

        ///  
        /// Waits for any of the provided  objects to complete execution.
        /// 
        /// 
        /// An array of  instances on which to wait. 
        /// 
        ///  
        /// A  to observe while waiting for a task to complete. 
        /// 
        ///  
        /// The index of the completed task in the  array argument.
        /// 
        /// 
        /// The  argument is null. 
        /// 
        ///  
        /// The  argument contains a null element. 
        /// 
        ///  
        /// The  has been disposed.
        /// 
        /// 
        /// The  was canceled. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static int WaitAny(Task[] tasks, CancellationToken cancellationToken) 
        {
            return WaitAny(tasks, Timeout.Infinite, cancellationToken); 
        }

        /// 
        /// Waits for any of the provided  objects to complete execution. 
        /// 
        ///  
        /// An array of  instances on which to wait. 
        /// 
        ///  
        /// The number of milliseconds to wait, or  (-1) to
        /// wait indefinitely.
        /// 
        ///  
        /// The index of the completed task in the  array argument, or -1 if the
        /// timeout occurred. 
        ///  
        /// 
        /// The  argument is null. 
        /// 
        /// 
        /// The  argument contains a null element.
        ///  
        /// 
        /// The  has been disposed. 
        ///  
        /// 
        ///  is a negative number other than -1, which represents an 
        /// infinite time-out.
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
        public static int WaitAny(Task[] tasks, int millisecondsTimeout) 
        {
            return WaitAny(tasks, millisecondsTimeout, CancellationToken.None); 
        } 

        ///  
        /// Waits for any of the provided  objects to complete execution.
        /// 
        /// 
        /// An array of  instances on which to wait. 
        /// 
        ///  
        /// The number of milliseconds to wait, or  (-1) to 
        /// wait indefinitely.
        ///  
        /// 
        /// A  to observe while waiting for a task to complete.
        /// 
        ///  
        /// The index of the completed task in the  array argument, or -1 if the
        /// timeout occurred. 
        ///  
        /// 
        /// The  argument is null. 
        /// 
        /// 
        /// The  argument contains a null element.
        ///  
        /// 
        /// The  has been disposed. 
        ///  
        /// 
        ///  is a negative number other than -1, which represents an 
        /// infinite time-out.
        /// 
        /// 
        /// The  was canceled. 
        /// 
        [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger 
        public static int WaitAny(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken) 
        {
            if (tasks == null) 
            {
                throw new ArgumentNullException("tasks");
            }
            if (millisecondsTimeout < -1) 
            {
                throw new ArgumentOutOfRangeException("millisecondsTimeout"); 
            } 

#if DEBUG 
            Contract.Assert(tasks != null && millisecondsTimeout >= -1, "invalid arguments passed to WaitAny");
#endif
            cancellationToken.ThrowIfCancellationRequested(); // early check before we make any allocations
 
            int signaledTaskIndex = -1;
 
            // Some logic to help us deal with > 63/64 tasks 

            // Count the number of spaces in a 64-element arrat that we can't take up with Task WaitHandles. 
            int numReservations = (cancellationToken.CanBeCanceled ? 1 : 0) +
                ((Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) ? 1 : 0);
            int threshold = 64 - numReservations; // this is the number of tasks that we can wait on w/o "overflow"
            int firstBucketCount = 0; // number of tasks to pass to WaitAny 
            int secondBucketCount = 0; // number of tasks to pass to ContinueWhenAny
            if (tasks.Length > threshold) 
            { 
                // we need to divide the tasks into primary and overflow groups
                firstBucketCount = threshold - 1; // need space for overflow task handle 
                secondBucketCount = tasks.Length - firstBucketCount;
            }
            else firstBucketCount = tasks.Length; // no need for overflow -- secondBucketCount remains at 0.
 
            // Fast path for situation where at least one task has already completed...
            for (int taskIndex = 0; taskIndex < tasks.Length; taskIndex++) 
            { 
                Task task = tasks[taskIndex];
 
                if (task == null)
                {
                    throw new ArgumentException(Environment.GetResourceString("Task_WaitMulti_NullTask"), "tasks");
                } 

                // functional specification of WaitAny requires an immediate throw if any of the tasks are disposed 
                // we will simply discard any other exceptions that have been accumulated so far 
                task.ThrowIfDisposed();
 
                if (task.IsCompleted)
                {
                    // one of the tasks is already completed, we'll record its index if we haven't encountered another completed task yet
                    if (signaledTaskIndex == -1) 
                    {
                        signaledTaskIndex = taskIndex; 
                    } 
                }
            } 

            // Return early if tasks array is valid and a task had already completed
            if (signaledTaskIndex != -1) return signaledTaskIndex;
 
            // Now that we're done with the fast path, allocate arrays for defensive copies.
            Task[] tasksLocalCopy1 = new Task[firstBucketCount]; //local copy needed in case 'tasks' is modified externally when we're in the 2nd loop 
            Task[] tasksLocalCopy2 = (secondBucketCount > 0) ? new Task[secondBucketCount] : null; // overflow array -- only allocate if necessary 

            // Due to potential ----s, we need to check for null/disposed/completed again 
            // as we build our defensive copy array(s).
            for (int taskIndex = 0; taskIndex < tasks.Length; taskIndex++)
            {
                Task task = tasks[taskIndex]; 

                if (task == null) 
                { 
                    throw new ArgumentException(Environment.GetResourceString("Task_WaitMulti_NullTask"), "tasks");
                } 

                // populate the local arrays
                if (taskIndex < firstBucketCount) tasksLocalCopy1[taskIndex] = task;
                else tasksLocalCopy2[taskIndex - firstBucketCount] = task; 

                // functional specification of WaitAny requires an immediate throw if any of the tasks are disposed 
                // we will simply discard any other exceptions that have been accumulated so far 
                task.ThrowIfDisposed();
 
                if (task.IsCompleted)
                {
                    // one of the tasks is already completed, we'll record its index if we haven't encountered another completed task yet
                    if (signaledTaskIndex == -1) 
                    {
                        signaledTaskIndex = taskIndex; 
                    } 
                }
            } 

            if (signaledTaskIndex == -1 && tasks.Length != 0)
            {
                // Calculate length of handle array. 
                int handleArrayLength = firstBucketCount +
                                        ((secondBucketCount > 0) ? 1 : 0) + // add one for overflow bucket 
                                        (cancellationToken.CanBeCanceled ? 1 : 0); // add one for "live" cancellation token 

                Contract.Assert(handleArrayLength <= 64, "Task.WaitAny(): handleArrayLength too long"); 

                Task continuation = null; // used for overflow tasks

                WaitHandle[] waitHandles = new WaitHandle[handleArrayLength]; 
                for (int i = 0; i < firstBucketCount; i++)
                { 
                    waitHandles[i] = tasksLocalCopy1[i].CompletedEvent.WaitHandle; 
                }
 
                if (secondBucketCount > 0)
                {
                    // Aggregate the overflow tasks into a ContinueWhenAny()
                    continuation = Task.Factory.ContinueWhenAny(tasksLocalCopy2, delegate(Task antecedent) 
                    {
                        // We don't get index info from ContinueWhenAny(), so we'll need to manually look up the index 
                        for (int i = 0; i < tasksLocalCopy2.Length; i++) 
                        {
                            if (antecedent == tasksLocalCopy2[i]) return i; 
                        }
                        return tasksLocalCopy2.Length; // this would indicate a problem
                    });
                    waitHandles[firstBucketCount] = continuation.CompletedEvent.WaitHandle; 
                }
 
                if (cancellationToken.CanBeCanceled) 
                {
                    // Add the CT at the end 
                    waitHandles[handleArrayLength - 1] = cancellationToken.WaitHandle;
                }

                int waitValue = WaitHandle.WaitAny(waitHandles, millisecondsTimeout, false); 

                cancellationToken.ThrowIfCancellationRequested(); 
 
                Contract.Assert(!cancellationToken.CanBeCanceled
                                || waitValue != handleArrayLength - 1); // this would mean a bug in CT.WH or the code above 

                if (waitValue != WaitHandle.WaitTimeout)
                {
                    // The final waitValue may need some further massaging 
                    if ((secondBucketCount > 0) && (waitValue == firstBucketCount))
                    { 
                        Contract.Assert(continuation.IsCompleted, "Task.WaitAny(): expected continuation to have completed."); 
                        Contract.Assert(continuation.Result < tasksLocalCopy2.Length, "Task.WaitAny(): internal accounting error.");
                        waitValue = firstBucketCount + continuation.Result; 
                    }
                    signaledTaskIndex = waitValue; // which may end up being WaitHandle.WaitTimeout
                }
            } 

            // We need to prevent the tasks array from being GC'ed until we come out of the wait. 
            // This is necessary so that the Parallel Debugger can traverse it during the long wait and deduce waiter/waitee relationships 
            GC.KeepAlive(tasks);
 
            return signaledTaskIndex;
        }

    } 

    // Proxy class for better debugging experience 
    internal class SystemThreadingTasks_TaskDebugView 
    {
        private Task m_task; 

        public SystemThreadingTasks_TaskDebugView(Task task)
        {
            m_task = task; 
        }
 
        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; } }
    } 

 
    // Special purpose derivation of Task that supports limited replication through 
    // overriding the ShouldReplicate() method.  This is used by the Parallel.For/ForEach
    // methods. 
    internal class ParallelForReplicatingTask : Task
    {
        // Member variables
        private int m_replicationDownCount; // downcounter to control replication 

        // 
        // Constructors 
        //
 
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
        internal ParallelForReplicatingTask(
            ParallelOptions parallelOptions, Action action, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions)
            : base(action, null, Task.InternalCurrent, CancellationToken.None, creationOptions, internalOptions | InternalTaskOptions.SelfReplicating, null) 
        {
            // Compute the down count based on scheduler/DOP info in parallelOptions. 
            m_replicationDownCount = parallelOptions.EffectiveMaxConcurrencyLevel; 

            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; 
            PossiblyCaptureContext(ref stackMark);
        }

 
        // Controls degree of replication.  If downcounter is initialized to -1, then
        // replication will be allowed to "run wild".  Otherwise, this method decrements 
        // the downcounter each time it is called, calling false when it is called with 
        // a zero downcounter.  This method returning false effectively ends the replication
        // of the associated ParallelForReplicatingTask. 
        internal override bool ShouldReplicate()
        {
            if (m_replicationDownCount == -1) return true; // "run wild"
 
            if (m_replicationDownCount > 0) // Decrement and return true if not called with 0 downcount
            { 
                m_replicationDownCount--; 
                return true;
            } 

            return false; // We're done replicating
        }
 
        internal override Task CreateReplicaTask(Action taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
                                            TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica) 
        { 
            return new ParallelForReplicaTask(taskReplicaDelegate, stateObject, parentTask, taskScheduler,
                                            creationOptionsForReplica, internalOptionsForReplica); 
        }


    } 

    internal class ParallelForReplicaTask : Task 
    { 
        internal object m_stateForNextReplica;  // some replicas may quit prematurely, in which case they will use this variable
        // to save state they want to be picked up by the next replica queued to the same thread 

        internal object m_stateFromPreviousReplica;  // some replicas may quit prematurely, in which case they will use this variable
        // to save state they want to be picked up by the next replica queued to the same thread
 
        internal Task m_handedOverChildReplica;  // some replicas may quit prematurely, in which case they will use this variable
        // to hand over the child replica they had queued to the next task that will replace them 
 
        internal ParallelForReplicaTask(Action taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
                                       TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica) : 
            base(taskReplicaDelegate, stateObject, parentTask, CancellationToken.None, creationOptionsForReplica, internalOptionsForReplica, taskScheduler)
        {
        }
 
        /// 
        /// In some cases a replica will want to quit prematurely (ie. before finishing a chunk of work it may have grabbed) 
        /// yet they will need the next replica to pick things up from where they left. This API is used to save such state. 
        ///
        /// Calling it is also the only way to record a premature exit. 
        /// 
        /// 
        internal void SaveStateForNextReplica(object stateForNextReplica)
        { 
            m_stateForNextReplica = stateForNextReplica;
        } 
 
        // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
        internal override Object SavedStateForNextReplica 
        {
            get { return m_stateForNextReplica; }

            set { m_stateForNextReplica = value; } 
        }
 
        // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica 
        internal override Object SavedStateFromPreviousReplica
        { 
            get { return m_stateFromPreviousReplica; }

            set { m_stateFromPreviousReplica = value; }
        } 

        // Allows internal deriving classes to support replicas that exit prematurely and want to hand over the child replica that they 
        // had queued, so that the replacement replica can work with that child task instead of queuing up yet another one 
        internal override Task HandedOverChildReplica
        { 
            get { return m_handedOverChildReplica; }

            set { m_handedOverChildReplica = value; }
        } 
    }
 
 
    /// 
    /// Specifies flags that control optional behavior for the creation and execution of tasks. 
    /// 
    [Flags]
    [Serializable]
    public enum TaskCreationOptions 
    {
        ///  
        /// Specifies that the default behavior should be used. 
        /// 
        None = 0x0, 

        /// 
        /// A hint to a TaskScheduler to schedule a
        /// task in as fair a manner as possible, meaning that tasks scheduled sooner will be more likely to 
        /// be run sooner, and tasks scheduled later will be more likely to be run later.
        ///  
        PreferFairness = 0x01, 

        ///  
        /// Specifies that a task will be a long-running, course-grained operation. It provides a hint to the
        /// TaskScheduler that oversubscription may be
        /// warranted.
        ///  
        LongRunning = 0x02,
 
        ///  
        /// Specifies that a task is attached to a parent in the task hierarchy.
        ///  
        AttachedToParent = 0x04,
    }

 
    /// 
    /// Task creation flags which are only used internally. 
    ///  
    [Flags]
    [Serializable] 
    internal enum InternalTaskOptions
    {
        ///  Specifies "No internal task options" 
        None, 

        /// Used to filter out internal vs. public task creation options. 
        InternalOptionsMask = 0x0000FF00, 

        ChildReplica = 0x0100, 
        ContinuationTask = 0x0200,
        PromiseTask = 0x0400,
        SelfReplicating = 0x0800,
 
        /// Specifies that the task will be queued by the runtime before handing it over to the user.
        /// This flag will be used to skip the cancellationtoken registration step, which is only meant for unstarted tasks. 
        QueuedByRuntime = 0x2000 
    }
 
    /// 
    /// Specifies flags that control optional behavior for the creation and execution of continuation tasks.
    /// 
    [Flags] 
    [Serializable]
    public enum TaskContinuationOptions 
    { 
        /// 
        /// Default = "Continue on any, no task options, run asynchronously" 
        /// Specifies that the default behavior should be used.  Continuations, by default, will
        /// be scheduled when the antecedent task completes, regardless of the task's final TaskStatus.
        ///  
        None = 0,
 
        // These are identical to their meanings and values in TaskCreationOptions 

        ///  
        /// A hint to a TaskScheduler to schedule a
        /// task in as fair a manner as possible, meaning that tasks scheduled sooner will be more likely to
        /// be run sooner, and tasks scheduled later will be more likely to be run later.
        ///  
        PreferFairness = 0x01,
 
        ///  
        /// Specifies that a task will be a long-running, course-grained operation.  It provides
        /// a hint to the TaskScheduler that 
        /// oversubscription may be warranted.
        /// 
        LongRunning = 0x02,
        ///  
        /// Specifies that a task is attached to a parent in the task hierarchy.
        ///  
        AttachedToParent = 0x04, 

        // These are specific to continuations 

        /// 
        /// Specifies that the continuation task should not be scheduled if its antecedent ran to completion.
        /// This option is not valid for multi-task continuations. 
        /// 
        NotOnRanToCompletion = 0x10000, 
        ///  
        /// Specifies that the continuation task should not be scheduled if its antecedent threw an unhandled
        /// exception. This option is not valid for multi-task continuations. 
        /// 
        NotOnFaulted = 0x20000,
        /// 
        /// Specifies that the continuation task should not be scheduled if its antecedent was canceled. This 
        /// option is not valid for multi-task continuations.
        ///  
        NotOnCanceled = 0x40000, 
        /// 
        /// Specifies that the continuation task should be scheduled only if its antecedent ran to 
        /// completion. This option is not valid for multi-task continuations.
        /// 
        OnlyOnRanToCompletion = NotOnFaulted | NotOnCanceled,
        ///  
        /// Specifies that the continuation task should be scheduled only if its antecedent threw an
        /// unhandled exception. This option is not valid for multi-task continuations. 
        ///  
        OnlyOnFaulted = NotOnRanToCompletion | NotOnCanceled,
        ///  
        /// Specifies that the continuation task should be scheduled only if its antecedent was canceled.
        /// This option is not valid for multi-task continuations.
        /// 
        OnlyOnCanceled = NotOnRanToCompletion | NotOnFaulted, 
        /// 
        /// Specifies that the continuation task should be executed synchronously. With this option 
        /// specified, the continuation will be run on the same thread that causes the antecedent task to 
        /// transition into its final state. If the antecedent is already complete when the continuation is
        /// created, the continuation will run on the thread creating the continuation.  Only very 
        /// short-running continuations should be executed synchronously.
        /// 
        ExecuteSynchronously = 0x80000
    } 

    ///  
    /// Internal helper class to keep track of stack depth and decide whether we should inline or not. 
    /// 
    internal class StackGuard 
    {
        // current thread's depth of nested inline task executions
        private int m_inliningDepth = 0;
 
        // For relatively small inlining depths we don't want to get into the business of stack probing etc.
        // This clearly leaves a window of opportunity for the user code to SO. However a piece of code 
        // that can SO in 20 inlines on a typical 1MB stack size probably needs to be revisited anyway. 
        private const int s_maxUncheckedInliningDepth = 20;
 
#if !FEATURE_PAL && !PFX_LEGACY_3_5

        private UInt64 m_lastKnownWatermark;
        private static int s_pageSize; 

        // We are conservative here. We assume that the platform needs a whole 64KB to 
        // respond to stack overflow. This means that for very small stacks (e.g. 128KB) 
        // we'll fail a lot of stack checks incorrectly.
        private const long STACK_RESERVED_SPACE = 4096 * 16; 

#endif  // !FEATURE_PAL && !PFX_LEGACY_3_5

        ///  
        /// This method needs to be called before attempting inline execution on the current thread.
        /// If false is returned, it means we are too close to the end of the stack and should give up inlining. 
        /// Each call to TryBeginInliningScope() that returns true must be matched with a 
        /// call to EndInliningScope() regardless of whether inlining actually took place.
        ///  
        [SecuritySafeCritical]
        internal bool TryBeginInliningScope()
        {
            // If we're still under the 'safe' limit we'll just skip the stack probe to save p/invoke calls 
            if (m_inliningDepth < s_maxUncheckedInliningDepth || CheckForSufficientStack())
            { 
                m_inliningDepth++; 
                return true;
            } 
            else
                return false;
        }
 
        /// 
        /// This needs to be called once for each previous successful TryBeginInliningScope() call after 
        /// inlining related logic runs. 
        /// 
        [SecuritySafeCritical] 
        internal void EndInliningScope()
        {
            m_inliningDepth--;
            Contract.Assert(m_inliningDepth >= 0, "Inlining depth count should never go negative."); 

            // do the right thing just in case... 
            if (m_inliningDepth < 0) m_inliningDepth = 0; 
        }
 
        [SecurityCritical]
        private unsafe bool CheckForSufficientStack()
        {
#if !FEATURE_PAL && !PFX_LEGACY_3_5 
            // see if we already have the system page size info recorded
            if (s_pageSize == 0) 
            { 
                // If not we need to query it from GetSystemInfo()
                // Note that this happens only once for the process lifetime 
                Win32Native.SYSTEM_INFO sysInfo = new Win32Native.SYSTEM_INFO();
                Win32Native.GetSystemInfo(ref sysInfo);

                s_pageSize = sysInfo.dwPageSize; 
            }
 
            Win32Native.MEMORY_BASIC_INFORMATION stackInfo = new Win32Native.MEMORY_BASIC_INFORMATION(); 

            // We subtract one page for our request. VirtualQuery rounds UP to the next page. 
            // Unfortunately, the stack grows down. If we're on the first page (last page in the
            // VirtualAlloc), we'll be moved to the next page, which is off the stack!

            UIntPtr currentAddr = new UIntPtr(&stackInfo - s_pageSize); 
            UInt64 current64 = currentAddr.ToUInt64();
 
            // Check whether we previously recorded a deeper stack than where we currently are, 
            // If so we don't need to do the P/Invoke to VirtualQuery
            if (m_lastKnownWatermark != 0 && current64 > m_lastKnownWatermark) 
                return true;

            // Actual stack probe. P/Invoke to query for the current stack allocation information.
            Win32Native.VirtualQuery(currentAddr.ToPointer(), ref stackInfo, new IntPtr(sizeof(Win32Native.MEMORY_BASIC_INFORMATION))); 

            // If the current address minus the base (remember: the stack grows downward in the 
            // address space) is greater than the number of bytes requested plus the reserved 
            // space at the end, the request has succeeded.
 
            if ((current64 - ((UIntPtr)stackInfo.AllocationBase).ToUInt64()) > STACK_RESERVED_SPACE)
            {
                m_lastKnownWatermark = current64;
                return true; 
            }
 
            return false; 

#else // !FEATURE_PAL && !PFX_LEGACY_3_5 

            // if we're being compiled with FEATURE_PAL or PFX_LEGACY_3_5 we simply allow unchecked inlining.
            return true;
#endif 
        }
    } 
 
}
 

// 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