Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / mscorlib / system / threading / Tasks / Task.cs
1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
7 //
8 // Task.cs
9 //
10 // <OWNER>[....]</OWNER>
11 //
12 // A schedulable unit of work.
13 //
14 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
15
16 using System;
17 using System.Collections.Generic;
18 using System.Collections.ObjectModel;
19 using System.Runtime;
20 using System.Runtime.CompilerServices;
21 using System.Runtime.InteropServices;
22 using System.Runtime.ExceptionServices;
23 using System.Security;
24 using System.Security.Permissions;
25 using System.Threading;
26 using System.Diagnostics;
27 using System.Diagnostics.Contracts;
28 using Microsoft.Win32;
29 using System.Diagnostics.Tracing;
30
31 // Disable the "reference to volatile field not treated as volatile" error.
32 #pragma warning disable 0420
33
34 namespace System.Threading.Tasks
35 {
36
37     /// <summary>
38     /// Utility class for allocating structs as heap variables
39     /// </summary>
40     internal class Shared<T>
41     {
42         internal T Value;
43
44         internal Shared(T value)
45         {
46             this.Value = value;
47         }
48
49     }
50
51     /// <summary>
52     /// Represents the current stage in the lifecycle of a <see cref="Task"/>.
53     /// </summary>
54     public enum TaskStatus
55     {
56         /// <summary> 
57         /// The task has been initialized but has not yet been scheduled.
58         /// </summary>
59         Created,
60         /// <summary> 
61         /// The task is waiting to be activated and scheduled internally by the .NET Framework infrastructure.
62         /// </summary>
63         WaitingForActivation,
64         /// <summary>
65         /// The task has been scheduled for execution but has not yet begun executing.
66         /// </summary>
67         WaitingToRun,
68         /// <summary>
69         /// The task is running but has not yet completed.
70         /// </summary>
71         Running,
72         // /// <summary>
73         // /// The task is currently blocked in a wait state.
74         // /// </summary>
75         // Blocked,
76         /// <summary>
77         /// The task has finished executing and is implicitly waiting for
78         /// attached child tasks to complete.
79         /// </summary>
80         WaitingForChildrenToComplete,
81         /// <summary>
82         /// The task completed execution successfully.
83         /// </summary>
84         RanToCompletion,
85         /// <summary>
86         /// The task acknowledged cancellation by throwing an OperationCanceledException with its own CancellationToken
87         /// while the token was in signaled state, or the task's CancellationToken was already signaled before the
88         /// task started executing.
89         /// </summary>
90         Canceled,
91         /// <summary>
92         /// The task completed due to an unhandled exception.
93         /// </summary>
94         Faulted
95     }
96
97     /// <summary>
98     /// Represents an asynchronous operation.
99     /// </summary>
100     /// <remarks>
101     /// <para>
102     /// <see cref="Task"/> instances may be created in a variety of ways. The most common approach is by
103     /// using the Task type's <see cref="Factory"/> property to retrieve a <see
104     /// cref="System.Threading.Tasks.TaskFactory"/> instance that can be used to create tasks for several
105     /// purposes. For example, to create a <see cref="Task"/> that runs an action, the factory's StartNew
106     /// method may be used:
107     /// <code>
108     /// // C# 
109     /// var t = Task.Factory.StartNew(() => DoAction());
110     /// 
111     /// ' Visual Basic 
112     /// Dim t = Task.Factory.StartNew(Function() DoAction())
113     /// </code>
114     /// </para>
115     /// <para>
116     /// The <see cref="Task"/> class also provides constructors that initialize the Task but that do not
117     /// schedule it for execution. For performance reasons, TaskFactory's StartNew method should be the
118     /// preferred mechanism for creating and scheduling computational tasks, but for scenarios where creation
119     /// and scheduling must be separated, the constructors may be used, and the task's <see cref="Start()"/>
120     /// method may then be used to schedule the task for execution at a later time.
121     /// </para>
122     /// <para>
123     /// All members of <see cref="Task"/>, except for <see cref="Dispose()"/>, are thread-safe
124     /// and may be used from multiple threads concurrently.
125     /// </para>
126     /// <para>
127     /// For operations that return values, the <see cref="System.Threading.Tasks.Task{TResult}"/> class
128     /// should be used.
129     /// </para>
130     /// <para>
131     /// For developers implementing custom debuggers, several internal and private members of Task may be
132     /// useful (these may change from release to release). The Int32 m_taskId field serves as the backing
133     /// store for the <see cref="Id"/> property, however accessing this field directly from a debugger may be
134     /// more efficient than accessing the same value through the property's getter method (the
135     /// s_taskIdCounter Int32 counter is used to retrieve the next available ID for a Task). Similarly, the
136     /// Int32 m_stateFlags field stores information about the current lifecycle stage of the Task,
137     /// information also accessible through the <see cref="Status"/> property. The m_action System.Object
138     /// field stores a reference to the Task's delegate, and the m_stateObject System.Object field stores the
139     /// async state passed to the Task by the developer. Finally, for debuggers that parse stack frames, the
140     /// InternalWait method serves a potential marker for when a Task is entering a wait operation.
141     /// </para>
142     /// </remarks>
143     [HostProtection(Synchronization = true, ExternalThreading = true)]
144     [DebuggerTypeProxy(typeof(SystemThreadingTasks_TaskDebugView))]
145     [DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}")]
146     public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable
147     {
148         [ThreadStatic]
149         internal static Task t_currentTask;  // The currently executing task.
150         [ThreadStatic]
151         private static StackGuard t_stackGuard;  // The stack guard object for this thread
152
153         internal static int s_taskIdCounter; //static counter used to generate unique task IDs
154         private readonly static TaskFactory s_factory = new TaskFactory();
155
156         private volatile int m_taskId; // this task's unique ID. initialized only if it is ever requested
157
158         internal object m_action;    // The body of the task.  Might be Action<object>, Action<TState> or Action.  Or possibly a Func.
159         // If m_action is set to null it will indicate that we operate in the
160         // "externally triggered completion" mode, which is exclusively meant 
161         // for the signalling Task<TResult> (aka. promise). In this mode,
162         // we don't call InnerInvoke() in response to a Wait(), but simply wait on
163         // the completion event which will be set when the Future class calls Finish().
164         // But the event would now be signalled if Cancel() is called
165
166
167         internal object m_stateObject; // A state object that can be optionally supplied, passed to action.
168         internal TaskScheduler m_taskScheduler; // The task scheduler this task runs under. 
169
170         internal readonly Task m_parent; // A task's parent, or null if parent-less.
171
172
173         internal volatile int m_stateFlags;
174
175         // State constants for m_stateFlags;
176         // The bits of m_stateFlags are allocated as follows:
177         //   0x40000000 - TaskBase state flag
178         //   0x3FFF0000 - Task state flags
179         //   0x0000FF00 - internal TaskCreationOptions flags
180         //   0x000000FF - publicly exposed TaskCreationOptions flags
181         //
182         // See TaskCreationOptions for bit values associated with TaskCreationOptions
183         //
184         private const int OptionsMask = 0xFFFF; // signifies the Options portion of m_stateFlags bin: 0000 0000 0000 0000 1111 1111 1111 1111
185         internal const int TASK_STATE_STARTED = 0x10000;                                       //bin: 0000 0000 0000 0001 0000 0000 0000 0000
186         internal const int TASK_STATE_DELEGATE_INVOKED = 0x20000;                              //bin: 0000 0000 0000 0010 0000 0000 0000 0000
187         internal const int TASK_STATE_DISPOSED = 0x40000;                                      //bin: 0000 0000 0000 0100 0000 0000 0000 0000
188         internal const int TASK_STATE_EXCEPTIONOBSERVEDBYPARENT = 0x80000;                     //bin: 0000 0000 0000 1000 0000 0000 0000 0000
189         internal const int TASK_STATE_CANCELLATIONACKNOWLEDGED = 0x100000;                     //bin: 0000 0000 0001 0000 0000 0000 0000 0000
190         internal const int TASK_STATE_FAULTED = 0x200000;                                      //bin: 0000 0000 0010 0000 0000 0000 0000 0000
191         internal const int TASK_STATE_CANCELED = 0x400000;                                     //bin: 0000 0000 0100 0000 0000 0000 0000 0000
192         internal const int TASK_STATE_WAITING_ON_CHILDREN = 0x800000;                          //bin: 0000 0000 1000 0000 0000 0000 0000 0000
193         internal const int TASK_STATE_RAN_TO_COMPLETION = 0x1000000;                           //bin: 0000 0001 0000 0000 0000 0000 0000 0000
194         internal const int TASK_STATE_WAITINGFORACTIVATION = 0x2000000;                        //bin: 0000 0010 0000 0000 0000 0000 0000 0000
195         internal const int TASK_STATE_COMPLETION_RESERVED = 0x4000000;                         //bin: 0000 0100 0000 0000 0000 0000 0000 0000
196         internal const int TASK_STATE_THREAD_WAS_ABORTED = 0x8000000;                          //bin: 0000 1000 0000 0000 0000 0000 0000 0000
197         internal const int TASK_STATE_WAIT_COMPLETION_NOTIFICATION = 0x10000000;               //bin: 0001 0000 0000 0000 0000 0000 0000 0000
198         //This could be moved to InternalTaskOptions enum
199         internal const int TASK_STATE_EXECUTIONCONTEXT_IS_NULL = 0x20000000;                   //bin: 0010 0000 0000 0000 0000 0000 0000 0000
200         internal const int TASK_STATE_TASKSCHEDULED_WAS_FIRED = 0x40000000;                    //bin: 0100 0000 0000 0000 0000 0000 0000 0000
201
202         // A mask for all of the final states a task may be in
203         private const int TASK_STATE_COMPLETED_MASK = TASK_STATE_CANCELED | TASK_STATE_FAULTED | TASK_STATE_RAN_TO_COMPLETION;
204
205         // Values for ContingentProperties.m_internalCancellationRequested.
206         private const int CANCELLATION_REQUESTED = 0x1;
207
208         // Can be null, a single continuation, a list of continuations, or s_taskCompletionSentinel,
209         // in that order. The logic arround this object assumes it will never regress to a previous state.
210         private volatile object m_continuationObject = null;
211
212         // m_continuationObject is set to this when the task completes.
213         private static readonly object s_taskCompletionSentinel = new object();
214
215         // A private flag that would be set (only) by the debugger
216         // When true the Async Causality logging trace is enabled as well as a dictionary to relate operation ids with Tasks
217         [FriendAccessAllowed]
218         internal static bool s_asyncDebuggingEnabled; //false by default
219
220         // This dictonary relates the task id, from an operation id located in the Async Causality log to the actual
221         // task. This is to be used by the debugger ONLY. Task in this dictionary represent current active tasks.
222         private static readonly Dictionary<int, Task> s_currentActiveTasks = new Dictionary<int, Task>();
223         private static readonly Object s_activeTasksLock = new Object();
224
225         // These methods are a way to access the dictionary both from this class and for other classes that also
226         // activate dummy tasks. Specifically the AsyncTaskMethodBuilder and AsyncTaskMethodBuilder<>
227         [FriendAccessAllowed]
228         internal static bool AddToActiveTasks(Task task)
229         {
230             Contract.Requires(task != null, "Null Task objects can't be added to the ActiveTasks collection");
231             lock (s_activeTasksLock)
232             {
233                 s_currentActiveTasks[task.Id] = task;
234             }
235             //always return true to keep signature as bool for backwards compatibility
236             return true;
237         }
238
239         [FriendAccessAllowed]
240         internal static void RemoveFromActiveTasks(int taskId)
241         {
242             lock (s_activeTasksLock)
243             {
244                 s_currentActiveTasks.Remove(taskId);
245             }
246         }
247
248         // We moved a number of Task properties into this class.  The idea is that in most cases, these properties never
249         // need to be accessed during the life cycle of a Task, so we don't want to instantiate them every time.  Once
250         // one of these properties needs to be written, we will instantiate a ContingentProperties object and set
251         // the appropriate property.
252         internal class ContingentProperties
253         {
254             // Additional context
255
256             internal ExecutionContext m_capturedContext; // The execution context to run the task within, if any.
257
258             // Completion fields (exceptions and event)
259
260             internal volatile ManualResetEventSlim m_completionEvent; // Lazily created if waiting is required.
261             internal volatile TaskExceptionHolder m_exceptionsHolder; // Tracks exceptions, if any have occurred
262
263             // Cancellation fields (token, registration, and internally requested)
264
265             internal CancellationToken m_cancellationToken; // Task's cancellation token, if it has one
266             internal Shared<CancellationTokenRegistration> m_cancellationRegistration; // Task's registration with the cancellation token
267             internal volatile int m_internalCancellationRequested; // Its own field because threads legally ---- to set it.
268
269             // Parenting fields
270
271             // # of active children + 1 (for this task itself).
272             // Used for ensuring all children are done before this task can complete
273             // The extra count helps prevent the ---- for executing the final state transition
274             // (i.e. whether the last child or this task itself should call FinishStageTwo())
275             internal volatile int m_completionCountdown = 1;
276             // A list of child tasks that threw an exception (TCEs don't count),
277             // but haven't yet been waited on by the parent, lazily initialized.
278             internal volatile List<Task> m_exceptionalChildren;
279
280             /// <summary>
281             /// Sets the internal completion event.
282             /// </summary>
283             internal void SetCompleted()
284             {
285                 var mres = m_completionEvent;
286                 if (mres != null) mres.Set();
287             }
288
289             /// <summary>
290             /// Checks if we registered a CT callback during construction, and deregisters it. 
291             /// This should be called when we know the registration isn't useful anymore. Specifically from Finish() if the task has completed
292             /// successfully or with an exception.
293             /// </summary>
294             internal void DeregisterCancellationCallback()
295             {
296                 if (m_cancellationRegistration != null)
297                 {
298                     // Harden against ODEs thrown from disposing of the CTR.
299                     // Since the task has already been put into a final state by the time this
300                     // is called, all we can do here is suppress the exception.
301                     try { m_cancellationRegistration.Value.Dispose(); }
302                     catch (ObjectDisposedException) { }
303                     m_cancellationRegistration = null;
304                 }
305             }
306         }
307
308
309         // This field will only be instantiated to some non-null value if any ContingentProperties need to be set.
310         // This will be a ContingentProperties instance or a type derived from it
311         internal volatile ContingentProperties m_contingentProperties;
312
313         // Special internal constructor to create an already-completed task.
314         // if canceled==true, create a Canceled task, or else create a RanToCompletion task.
315         // Constructs the task as already completed
316         internal Task(bool canceled, TaskCreationOptions creationOptions, CancellationToken ct)
317         {
318             int optionFlags = (int)creationOptions;
319             if (canceled)
320             {
321                 m_stateFlags = TASK_STATE_CANCELED | TASK_STATE_CANCELLATIONACKNOWLEDGED | optionFlags;
322                 ContingentProperties props;
323                 m_contingentProperties = props = new ContingentProperties(); // can't have children, so just instantiate directly
324                 props.m_cancellationToken = ct;
325                 props.m_internalCancellationRequested = CANCELLATION_REQUESTED;
326             }
327             else
328                 m_stateFlags = TASK_STATE_RAN_TO_COMPLETION | optionFlags;
329         }
330
331         // Uncomment if/when we want Task.FromException
332         //// Special internal constructor to create an already-Faulted task.
333         //internal Task(Exception exception)
334         //{
335         //    Contract.Assert(exception != null);
336         //    ContingentProperties props;
337         //    m_contingentProperties = props = new ContingentProperties(); // can't have children, so just instantiate directly
338         //    props.m_exceptionsHolder.Add(exception);
339         //    m_stateFlags = TASK_STATE_FAULTED;
340         //}
341
342         /// <summary>Constructor for use with promise-style tasks that aren't configurable.</summary>
343         internal Task()
344         {
345             m_stateFlags = TASK_STATE_WAITINGFORACTIVATION | (int)InternalTaskOptions.PromiseTask;
346         }
347
348         // Special constructor for use with promise-style tasks.
349         // Added promiseStyle parameter as an aid to the compiler to distinguish between (state,TCO) and
350         // (action,TCO).  It should always be true.
351         internal Task(object state, TaskCreationOptions creationOptions, bool promiseStyle)
352         {
353             Contract.Assert(promiseStyle, "Promise CTOR: promiseStyle was false");
354
355             // Check the creationOptions. We allow the AttachedToParent option to be specified for promise tasks.
356             // Also allow RunContinuationsAsynchronously because this is the constructor called by TCS
357             if ((creationOptions & ~(TaskCreationOptions.AttachedToParent | TaskCreationOptions.RunContinuationsAsynchronously)) != 0)
358             {
359                 throw new ArgumentOutOfRangeException("creationOptions");
360             }
361
362             // m_parent is readonly, and so must be set in the constructor.
363             // Only set a parent if AttachedToParent is specified.
364             if ((creationOptions & TaskCreationOptions.AttachedToParent) != 0)
365                 m_parent = Task.InternalCurrent;
366
367             TaskConstructorCore(null, state, default(CancellationToken), creationOptions, InternalTaskOptions.PromiseTask, null);
368         }
369
370         /// <summary>
371         /// Initializes a new <see cref="Task"/> with the specified action.
372         /// </summary>
373         /// <param name="action">The delegate that represents the code to execute in the Task.</param>
374         /// <exception cref="T:System.ArgumentNullException">The <paramref name="action"/> argument is null.</exception>
375         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
376         public Task(Action action)
377             : this(action, null, null, default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null)
378         {
379             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
380             PossiblyCaptureContext(ref stackMark);
381         }
382
383         /// <summary>
384         /// Initializes a new <see cref="Task"/> with the specified action and <see cref="System.Threading.CancellationToken">CancellationToken</see>.
385         /// </summary>
386         /// <param name="action">The delegate that represents the code to execute in the Task.</param>
387         /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
388         /// that will be assigned to the new Task.</param>
389         /// <exception cref="T:System.ArgumentNullException">The <paramref name="action"/> argument is null.</exception>
390         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
391         /// has already been disposed.
392         /// </exception>
393         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
394         public Task(Action action, CancellationToken cancellationToken)
395             : this(action, null, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
396         {
397             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
398             PossiblyCaptureContext(ref stackMark);
399         }
400
401         /// <summary>
402         /// Initializes a new <see cref="Task"/> with the specified action and creation options.
403         /// </summary>
404         /// <param name="action">The delegate that represents the code to execute in the task.</param>
405         /// <param name="creationOptions">
406         /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
407         /// customize the Task's behavior.
408         /// </param>
409         /// <exception cref="T:System.ArgumentNullException">
410         /// The <paramref name="action"/> argument is null.
411         /// </exception>
412         /// <exception cref="T:System.ArgumentOutOfRangeException">
413         /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
414         /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
415         /// </exception>
416         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
417         public Task(Action action, TaskCreationOptions creationOptions)
418             : this(action, null, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, InternalTaskOptions.None, null)
419         {
420             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
421             PossiblyCaptureContext(ref stackMark);
422         }
423
424         /// <summary>
425         /// Initializes a new <see cref="Task"/> with the specified action and creation options.
426         /// </summary>
427         /// <param name="action">The delegate that represents the code to execute in the task.</param>
428         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
429         /// <param name="creationOptions">
430         /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
431         /// customize the Task's behavior.
432         /// </param>
433         /// <exception cref="T:System.ArgumentNullException">
434         /// The <paramref name="action"/> argument is null.
435         /// </exception>
436         /// <exception cref="T:System.ArgumentOutOfRangeException">
437         /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
438         /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
439         /// </exception>
440         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
441         /// has already been disposed.
442         /// </exception>
443         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
444         public Task(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
445             : this(action, null, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
446         {
447             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
448             PossiblyCaptureContext(ref stackMark);
449         }
450
451
452         /// <summary>
453         /// Initializes a new <see cref="Task"/> with the specified action and state.
454         /// </summary>
455         /// <param name="action">The delegate that represents the code to execute in the task.</param>
456         /// <param name="state">An object representing data to be used by the action.</param>
457         /// <exception cref="T:System.ArgumentNullException">
458         /// The <paramref name="action"/> argument is null.
459         /// </exception>
460         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
461         public Task(Action<object> action, object state)
462             : this(action, state, null, default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null)
463         {
464             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
465             PossiblyCaptureContext(ref stackMark);
466         }
467
468         /// <summary>
469         /// Initializes a new <see cref="Task"/> with the specified action, state, snd options.
470         /// </summary>
471         /// <param name="action">The delegate that represents the code to execute in the task.</param>
472         /// <param name="state">An object representing data to be used by the action.</param>
473         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
474         /// <exception cref="T:System.ArgumentNullException">
475         /// The <paramref name="action"/> argument is null.
476         /// </exception>
477         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
478         /// has already been disposed.
479         /// </exception>
480         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
481         public Task(Action<object> action, object state, CancellationToken cancellationToken)
482             : this(action, state, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
483         {
484             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
485             PossiblyCaptureContext(ref stackMark);
486         }
487
488         /// <summary>
489         /// Initializes a new <see cref="Task"/> with the specified action, state, snd options.
490         /// </summary>
491         /// <param name="action">The delegate that represents the code to execute in the task.</param>
492         /// <param name="state">An object representing data to be used by the action.</param>
493         /// <param name="creationOptions">
494         /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
495         /// customize the Task's behavior.
496         /// </param>
497         /// <exception cref="T:System.ArgumentNullException">
498         /// The <paramref name="action"/> argument is null.
499         /// </exception>
500         /// <exception cref="T:System.ArgumentOutOfRangeException">
501         /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
502         /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
503         /// </exception>
504         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
505         public Task(Action<object> action, object state, TaskCreationOptions creationOptions)
506             : this(action, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, InternalTaskOptions.None, null)
507         {
508             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
509             PossiblyCaptureContext(ref stackMark);
510         }
511
512         /// <summary>
513         /// Initializes a new <see cref="Task"/> with the specified action, state, snd options.
514         /// </summary>
515         /// <param name="action">The delegate that represents the code to execute in the task.</param>
516         /// <param name="state">An object representing data to be used by the action.</param>
517         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
518         /// <param name="creationOptions">
519         /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
520         /// customize the Task's behavior.
521         /// </param>
522         /// <exception cref="T:System.ArgumentNullException">
523         /// The <paramref name="action"/> argument is null.
524         /// </exception>
525         /// <exception cref="T:System.ArgumentOutOfRangeException">
526         /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
527         /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
528         /// </exception>
529         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
530         /// has already been disposed.
531         /// </exception>
532         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
533         public Task(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
534             : this(action, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
535         {
536             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
537             PossiblyCaptureContext(ref stackMark);
538         }
539
540         internal Task(Action<object> action, object state, Task parent, CancellationToken cancellationToken,
541             TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark)
542             : this(action, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
543         {
544             PossiblyCaptureContext(ref stackMark);
545         }
546
547         /// <summary>
548         /// An internal constructor used by the factory methods on task and its descendent(s).
549         /// This variant does not capture the ExecutionContext; it is up to the caller to do that.
550         /// </summary>
551         /// <param name="action">An action to execute.</param>
552         /// <param name="state">Optional state to pass to the action.</param>
553         /// <param name="parent">Parent of Task.</param>
554         /// <param name="cancellationToken">A CancellationToken for the task.</param>
555         /// <param name="scheduler">A task scheduler under which the task will run.</param>
556         /// <param name="creationOptions">Options to control its execution.</param>
557         /// <param name="internalOptions">Internal options to control its execution</param>
558         internal Task(Delegate action, object state, Task parent, CancellationToken cancellationToken,
559             TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
560         {
561             if (action == null)
562             {
563                 throw new ArgumentNullException("action");
564             }
565             Contract.EndContractBlock();
566
567             // This is readonly, and so must be set in the constructor
568             // Keep a link to your parent if: (A) You are attached, or (B) you are self-replicating.
569             if (((creationOptions & TaskCreationOptions.AttachedToParent) != 0) ||
570                 ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
571                 )
572             {
573                 m_parent = parent;
574             }
575
576             TaskConstructorCore(action, state, cancellationToken, creationOptions, internalOptions, scheduler);
577         }
578
579         /// <summary>
580         /// Common logic used by the following internal ctors:
581         ///     Task()
582         ///     Task(object action, object state, Task parent, TaskCreationOptions options, TaskScheduler taskScheduler)
583         /// </summary>
584         /// <param name="action">Action for task to execute.</param>
585         /// <param name="state">Object to which to pass to action (may be null)</param>
586         /// <param name="scheduler">Task scheduler on which to run thread (only used by continuation tasks).</param>
587         /// <param name="cancellationToken">A CancellationToken for the Task.</param>
588         /// <param name="creationOptions">Options to customize behavior of Task.</param>
589         /// <param name="internalOptions">Internal options to customize behavior of Task.</param>
590         internal void TaskConstructorCore(object action, object state, CancellationToken cancellationToken,
591             TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
592         {
593             m_action = action;
594             m_stateObject = state;
595             m_taskScheduler = scheduler;
596
597             // Check for validity of options
598             if ((creationOptions &
599                     ~(TaskCreationOptions.AttachedToParent |
600                       TaskCreationOptions.LongRunning |
601                       TaskCreationOptions.DenyChildAttach |
602                       TaskCreationOptions.HideScheduler |
603                       TaskCreationOptions.PreferFairness |
604                       TaskCreationOptions.RunContinuationsAsynchronously)) != 0)
605             {
606                 throw new ArgumentOutOfRangeException("creationOptions");
607             }
608
609 #if DEBUG
610             // Check the validity of internalOptions
611             int illegalInternalOptions = 
612                     (int) (internalOptions &
613                             ~(InternalTaskOptions.SelfReplicating |
614                               InternalTaskOptions.ChildReplica |
615                               InternalTaskOptions.PromiseTask |
616                               InternalTaskOptions.ContinuationTask |
617                               InternalTaskOptions.LazyCancellation |
618                               InternalTaskOptions.QueuedByRuntime));
619             Contract.Assert(illegalInternalOptions == 0, "TaskConstructorCore: Illegal internal options");
620 #endif
621
622             // Throw exception if the user specifies both LongRunning and SelfReplicating
623             if (((creationOptions & TaskCreationOptions.LongRunning) != 0) &&
624                 ((internalOptions & InternalTaskOptions.SelfReplicating) != 0))
625             {
626                 throw new InvalidOperationException(Environment.GetResourceString("Task_ctor_LRandSR"));
627             }
628
629             // Assign options to m_stateAndOptionsFlag.
630             Contract.Assert(m_stateFlags == 0, "TaskConstructorCore: non-zero m_stateFlags");
631             Contract.Assert((((int)creationOptions) | OptionsMask) == OptionsMask, "TaskConstructorCore: options take too many bits");
632             var tmpFlags = (int)creationOptions | (int)internalOptions;
633             if ((m_action == null) || ((internalOptions & InternalTaskOptions.ContinuationTask) != 0))
634             {
635                 // For continuation tasks or TaskCompletionSource.Tasks, begin life in the 
636                 // WaitingForActivation state rather than the Created state.
637                 tmpFlags |= TASK_STATE_WAITINGFORACTIVATION;
638             }
639             m_stateFlags = tmpFlags; // one write to the volatile m_stateFlags instead of two when setting the above options
640
641             // Now is the time to add the new task to the children list 
642             // of the creating task if the options call for it.
643             // We can safely call the creator task's AddNewChild() method to register it, 
644             // because at this point we are already on its thread of execution.
645
646             if (m_parent != null
647                 && ((creationOptions & TaskCreationOptions.AttachedToParent) != 0)
648                 && ((m_parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0)
649                 )
650             {
651                 m_parent.AddNewChild();
652             }
653
654             // if we have a non-null cancellationToken, allocate the contingent properties to save it
655             // we need to do this as the very last thing in the construction path, because the CT registration could modify m_stateFlags
656             if (cancellationToken.CanBeCanceled)
657             {
658                 Contract.Assert((internalOptions &
659                     (InternalTaskOptions.ChildReplica | InternalTaskOptions.SelfReplicating | InternalTaskOptions.ContinuationTask)) == 0,
660                     "TaskConstructorCore: Did not expect to see cancelable token for replica/replicating or continuation task.");
661
662                 AssignCancellationToken(cancellationToken, null, null);
663             }
664         }
665
666         /// <summary>
667         /// Handles everything needed for associating a CancellationToken with a task which is being constructed.
668         /// This method is meant to be be called either from the TaskConstructorCore or from ContinueWithCore.
669         /// </summary>
670         private void AssignCancellationToken(CancellationToken cancellationToken, Task antecedent, TaskContinuation continuation)
671         {
672             // There is no need to worry about concurrency issues here because we are in the constructor path of the task --
673             // there should not be any ----s to set m_contingentProperties at this point.
674             ContingentProperties props = EnsureContingentPropertiesInitialized(needsProtection: false);
675             props.m_cancellationToken = cancellationToken;
676
677             try
678             {
679                 if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
680                 {
681                     cancellationToken.ThrowIfSourceDisposed();
682                 }
683
684                 // If an unstarted task has a valid CancellationToken that gets signalled while the task is still not queued
685                 // we need to proactively cancel it, because it may never execute to transition itself. 
686                 // The only way to accomplish this is to register a callback on the CT.
687                 // We exclude Promise tasks from this, because TaskCompletionSource needs to fully control the inner tasks's lifetime (i.e. not allow external cancellations)
688                 if ((((InternalTaskOptions)Options &
689                     (InternalTaskOptions.QueuedByRuntime | InternalTaskOptions.PromiseTask | InternalTaskOptions.LazyCancellation)) == 0))
690                 {
691                     if (cancellationToken.IsCancellationRequested)
692                     {
693                         // Fast path for an already-canceled cancellationToken
694                         this.InternalCancel(false);
695                     }
696                     else
697                     {
698                         // Regular path for an uncanceled cancellationToken
699                         CancellationTokenRegistration ctr;
700                         if (antecedent == null)
701                         {
702                             // if no antecedent was specified, use this task's reference as the cancellation state object
703                             ctr = cancellationToken.InternalRegisterWithoutEC(s_taskCancelCallback, this);
704                         }
705                         else
706                         {
707                             // If an antecedent was specified, pack this task, its antecedent and the TaskContinuation together as a tuple 
708                             // and use it as the cancellation state object. This will be unpacked in the cancellation callback so that 
709                             // antecedent.RemoveCancellation(continuation) can be invoked.
710                             ctr = cancellationToken.InternalRegisterWithoutEC(s_taskCancelCallback,
711                                                                               new Tuple<Task, Task, TaskContinuation>(this, antecedent, continuation));
712                         }
713
714                         props.m_cancellationRegistration = new Shared<CancellationTokenRegistration>(ctr);
715                     }
716                 }
717             }
718             catch
719             {
720                 // If we have an exception related to our CancellationToken, then we need to subtract ourselves
721                 // from our parent before throwing it.
722                 if ((m_parent != null) &&
723                     ((Options & TaskCreationOptions.AttachedToParent) != 0)
724                      && ((m_parent.Options & TaskCreationOptions.DenyChildAttach) == 0))
725                 {
726                     m_parent.DisregardChild();
727                 }
728                 throw;
729             }
730         }
731
732
733         // Static delegate to be used as a cancellation callback on unstarted tasks that have a valid cancellation token.
734         // This is necessary to transition them into canceled state if their cancellation token is signalled while they are still not queued
735         private readonly static Action<Object> s_taskCancelCallback = new Action<Object>(TaskCancelCallback);
736         private static void TaskCancelCallback(Object o)
737         {
738             var targetTask = o as Task;
739             if (targetTask == null)
740             {
741                 var tuple = o as Tuple<Task, Task, TaskContinuation>;
742                 if (tuple != null)
743                 {
744                     targetTask = tuple.Item1;
745
746                     Task antecedentTask = tuple.Item2;
747                     TaskContinuation continuation = tuple.Item3;
748                     antecedentTask.RemoveContinuation(continuation);
749                 }
750             }
751             Contract.Assert(targetTask != null,
752                 "targetTask should have been non-null, with the supplied argument being a task or a tuple containing one");
753             targetTask.InternalCancel(false);
754         }
755
756         // Debugger support
757         private string DebuggerDisplayMethodDescription
758         {
759             get
760             {
761                 Delegate d = (Delegate)m_action;
762                 return d != null ? d.Method.ToString() : "{null}";
763             }
764         }
765
766
767         /// <summary>
768         /// Captures the ExecutionContext so long as flow isn't suppressed.
769         /// </summary>
770         /// <param name="stackMark">A stack crawl mark pointing to the frame of the caller.</param>
771
772         [SecuritySafeCritical]
773         internal void PossiblyCaptureContext(ref StackCrawlMark stackMark)
774         {
775             Contract.Assert(m_contingentProperties == null || m_contingentProperties.m_capturedContext == null,
776                 "Captured an ExecutionContext when one was already captured.");
777
778             // In the legacy .NET 3.5 build, we don't have the optimized overload of Capture()
779             // available, so we call the parameterless overload.
780 #if PFX_LEGACY_3_5
781             CapturedContext = ExecutionContext.Capture();
782 #else
783             CapturedContext = ExecutionContext.Capture(
784                 ref stackMark,
785                 ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase);
786 #endif
787         }
788
789         // Internal property to process TaskCreationOptions access and mutation.
790         internal TaskCreationOptions Options
791         {
792             get
793             {
794                 int stateFlags = m_stateFlags; // "cast away" volatility to enable inlining of OptionsMethod
795                 return OptionsMethod(stateFlags);
796             }
797         }
798
799         // Similar to Options property, but allows for the use of a cached flags value rather than
800         // a read of the volatile m_stateFlags field.
801         internal static TaskCreationOptions OptionsMethod(int flags)
802         {
803             Contract.Assert((OptionsMask & 1) == 1, "OptionsMask needs a shift in Options.get");
804             return (TaskCreationOptions)(flags & OptionsMask);
805         }
806
807         // Atomically OR-in newBits to m_stateFlags, while making sure that
808         // no illegalBits are set.  Returns true on success, false on failure.
809         internal bool AtomicStateUpdate(int newBits, int illegalBits)
810         {
811             // This could be implemented in terms of:
812             //     internal bool AtomicStateUpdate(int newBits, int illegalBits, ref int oldFlags);
813             // but for high-throughput perf, that delegation's cost is noticeable.
814
815             SpinWait sw = new SpinWait();
816             do
817             {
818                 int oldFlags = m_stateFlags;
819                 if ((oldFlags & illegalBits) != 0) return false;
820                 if (Interlocked.CompareExchange(ref m_stateFlags, oldFlags | newBits, oldFlags) == oldFlags)
821                 {
822                     return true;
823                 }
824                 sw.SpinOnce();
825             } while (true);
826         }
827
828         internal bool AtomicStateUpdate(int newBits, int illegalBits, ref int oldFlags)
829         {
830             SpinWait sw = new SpinWait();
831             do
832             {
833                 oldFlags = m_stateFlags;
834                 if ((oldFlags & illegalBits) != 0) return false;
835                 if (Interlocked.CompareExchange(ref m_stateFlags, oldFlags | newBits, oldFlags) == oldFlags)
836                 {
837                     return true;
838                 }
839                 sw.SpinOnce();
840             } while (true);
841         }
842
843         /// <summary>
844         /// Sets or clears the TASK_STATE_WAIT_COMPLETION_NOTIFICATION state bit.
845         /// The debugger sets this bit to aid it in "stepping out" of an async method body.
846         /// If enabled is true, this must only be called on a task that has not yet been completed.
847         /// If enabled is false, this may be called on completed tasks.
848         /// Either way, it should only be used for promise-style tasks.
849         /// </summary>
850         /// <param name="enabled">true to set the bit; false to unset the bit.</param>
851         internal void SetNotificationForWaitCompletion(bool enabled)
852         {
853             Contract.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0,
854                 "Should only be used for promise-style tasks"); // hasn't been vetted on other kinds as there hasn't been a need
855
856             if (enabled)
857             {
858                 // Atomically set the END_AWAIT_NOTIFICATION bit
859                 bool success = AtomicStateUpdate(TASK_STATE_WAIT_COMPLETION_NOTIFICATION,
860                                   TASK_STATE_COMPLETED_MASK | TASK_STATE_COMPLETION_RESERVED);
861                 Contract.Assert(success, "Tried to set enabled on completed Task");
862             }
863             else
864             {
865                 // Atomically clear the END_AWAIT_NOTIFICATION bit
866                 SpinWait sw = new SpinWait();
867                 while (true)
868                 {
869                     int oldFlags = m_stateFlags;
870                     int newFlags = oldFlags & (~TASK_STATE_WAIT_COMPLETION_NOTIFICATION);
871                     if (Interlocked.CompareExchange(ref m_stateFlags, newFlags, oldFlags) == oldFlags) break;
872                     sw.SpinOnce();
873                 }
874             }
875         }
876
877         /// <summary>
878         /// Calls the debugger notification method if the right bit is set and if
879         /// the task itself allows for the notification to proceed.
880         /// </summary>
881         /// <returns>true if the debugger was notified; otherwise, false.</returns>
882         internal bool NotifyDebuggerOfWaitCompletionIfNecessary()
883         {
884             // Notify the debugger if of any of the tasks we've waited on requires notification
885             if (IsWaitNotificationEnabled && ShouldNotifyDebuggerOfWaitCompletion)
886             {
887                 NotifyDebuggerOfWaitCompletion();
888                 return true;
889             }
890             return false;
891         }
892
893         /// <summary>Returns true if any of the supplied tasks require wait notification.</summary>
894         /// <param name="tasks">The tasks to check.</param>
895         /// <returns>true if any of the tasks require notification; otherwise, false.</returns>
896         internal static bool AnyTaskRequiresNotifyDebuggerOfWaitCompletion(Task[] tasks)
897         {
898             Contract.Assert(tasks != null, "Expected non-null array of tasks");
899             foreach (var task in tasks)
900             {
901                 if (task != null &&
902                     task.IsWaitNotificationEnabled &&
903                     task.ShouldNotifyDebuggerOfWaitCompletion) // potential recursion
904                 {
905                     return true;
906                 }
907             }
908             return false;
909         }
910
911         /// <summary>Gets whether either the end await bit is set or (not xor) the task has not completed successfully.</summary>
912         /// <returns>(DebuggerBitSet || !RanToCompletion)</returns>
913         internal bool IsWaitNotificationEnabledOrNotRanToCompletion
914         {
915             [MethodImpl(MethodImplOptions.AggressiveInlining)]
916             get
917             {
918                 return (m_stateFlags & (Task.TASK_STATE_WAIT_COMPLETION_NOTIFICATION | Task.TASK_STATE_RAN_TO_COMPLETION))
919                         != Task.TASK_STATE_RAN_TO_COMPLETION;
920             }
921         }
922
923         /// <summary>
924         /// Determines whether we should inform the debugger that we're ending a join with a task.  
925         /// This should only be called if the debugger notification bit is set, as it is has some cost,
926         /// namely it is a virtual call (however calling it if the bit is not set is not functionally 
927         /// harmful).  Derived implementations may choose to only conditionally call down to this base 
928         /// implementation.
929         /// </summary>
930         internal virtual bool ShouldNotifyDebuggerOfWaitCompletion // ideally would be familyAndAssembly, but that can't be done in C#
931         {
932             get
933             {
934                 // It's theoretically possible but extremely rare that this assert could fire because the 
935                 // bit was unset between the time that it was checked and this method was called.
936                 // It's so remote a chance that it's worth having the assert to protect against misuse.
937                 bool isWaitNotificationEnabled = IsWaitNotificationEnabled;
938                 Contract.Assert(isWaitNotificationEnabled, "Should only be called if the wait completion bit is set.");
939                 return isWaitNotificationEnabled;
940             }
941         }
942
943         /// <summary>Gets whether the task's debugger notification for wait completion bit is set.</summary>
944         /// <returns>true if the bit is set; false if it's not set.</returns>
945         internal bool IsWaitNotificationEnabled // internal only to enable unit tests; would otherwise be private
946         {
947             get { return (m_stateFlags & TASK_STATE_WAIT_COMPLETION_NOTIFICATION) != 0; }
948         }
949
950         /// <summary>Placeholder method used as a breakpoint target by the debugger.  Must not be inlined or optimized.</summary>
951         /// <remarks>All joins with a task should end up calling this if their debugger notification bit is set.</remarks>
952         [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
953         private void NotifyDebuggerOfWaitCompletion()
954         {
955             // It's theoretically possible but extremely rare that this assert could fire because the 
956             // bit was unset between the time that it was checked and this method was called.
957             // It's so remote a chance that it's worth having the assert to protect against misuse.
958             Contract.Assert(IsWaitNotificationEnabled, "Should only be called if the wait completion bit is set.");
959
960             // Now that we're notifying the debugger, clear the bit.  The debugger should do this anyway,
961             // but this adds a bit of protection in case it fails to, and given that the debugger is involved, 
962             // the overhead here for the interlocked is negligable.  We do still rely on the debugger
963             // to clear bits, as this doesn't recursively clear bits in the case of, for example, WhenAny.
964             SetNotificationForWaitCompletion(enabled: false);
965         }
966
967
968         // Atomically mark a Task as started while making sure that it is not canceled.
969         internal bool MarkStarted()
970         {
971             return AtomicStateUpdate(TASK_STATE_STARTED, TASK_STATE_CANCELED | TASK_STATE_STARTED);
972         }
973
974         [MethodImpl(MethodImplOptions.AggressiveInlining)]
975         internal bool FireTaskScheduledIfNeeded(TaskScheduler ts)
976         {
977             var etwLog = TplEtwProvider.Log;
978             if (etwLog.IsEnabled() && (m_stateFlags & Task.TASK_STATE_TASKSCHEDULED_WAS_FIRED) == 0)
979             {
980                 m_stateFlags |= Task.TASK_STATE_TASKSCHEDULED_WAS_FIRED;
981
982                 Task currentTask = Task.InternalCurrent;
983                 Task parentTask = this.m_parent;
984                 etwLog.TaskScheduled(ts.Id, currentTask == null ? 0 : currentTask.Id,
985                                      this.Id, parentTask == null ? 0 : parentTask.Id, (int)this.Options,
986                                      System.Threading.Thread.GetDomainID());
987                 return true;
988             }
989             else
990                 return false;
991         }
992
993         /// <summary>
994         /// Internal function that will be called by a new child task to add itself to 
995         /// the children list of the parent (this).
996         /// 
997         /// Since a child task can only be created from the thread executing the action delegate
998         /// of this task, reentrancy is neither required nor supported. This should not be called from
999         /// anywhere other than the task construction/initialization codepaths.
1000         /// </summary>
1001         internal void AddNewChild()
1002         {
1003             Contract.Assert(Task.InternalCurrent == this || this.IsSelfReplicatingRoot, "Task.AddNewChild(): Called from an external context");
1004
1005             var props = EnsureContingentPropertiesInitialized(needsProtection: true);
1006
1007             if (props.m_completionCountdown == 1 && !IsSelfReplicatingRoot)
1008             {
1009                 // A count of 1 indicates so far there was only the parent, and this is the first child task
1010                 // Single kid => no fuss about who else is accessing the count. Let's save ourselves 100 cycles
1011                 // We exclude self replicating root tasks from this optimization, because further child creation can take place on 
1012                 // other cores and with bad enough timing this write may not be visible to them.
1013                 props.m_completionCountdown++;
1014             }
1015             else
1016             {
1017                 // otherwise do it safely
1018                 Interlocked.Increment(ref props.m_completionCountdown);
1019             }
1020         }
1021
1022         // This is called in the case where a new child is added, but then encounters a CancellationToken-related exception.
1023         // We need to subtract that child from m_completionCountdown, or the parent will never complete.
1024         internal void DisregardChild()
1025         {
1026             Contract.Assert(Task.InternalCurrent == this, "Task.DisregardChild(): Called from an external context");
1027
1028             var props = EnsureContingentPropertiesInitialized(needsProtection: true);
1029             Contract.Assert(props.m_completionCountdown >= 2, "Task.DisregardChild(): Expected parent count to be >= 2");
1030             Interlocked.Decrement(ref props.m_completionCountdown);
1031         }
1032
1033         /// <summary>
1034         /// Starts the <see cref="Task"/>, scheduling it for execution to the current <see
1035         /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>.
1036         /// </summary>
1037         /// <remarks>
1038         /// A task may only be started and run only once.  Any attempts to schedule a task a second time
1039         /// will result in an exception.
1040         /// </remarks>
1041         /// <exception cref="InvalidOperationException">
1042         /// The <see cref="Task"/> is not in a valid state to be started. It may have already been started,
1043         /// executed, or canceled, or it may have been created in a manner that doesn't support direct
1044         /// scheduling.
1045         /// </exception>
1046         public void Start()
1047         {
1048             Start(TaskScheduler.Current);
1049         }
1050
1051         /// <summary>
1052         /// Starts the <see cref="Task"/>, scheduling it for execution to the specified <see
1053         /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>.
1054         /// </summary>
1055         /// <remarks>
1056         /// A task may only be started and run only once. Any attempts to schedule a task a second time will
1057         /// result in an exception.
1058         /// </remarks>
1059         /// <param name="scheduler">
1060         /// The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> with which to associate
1061         /// and execute this task.
1062         /// </param>
1063         /// <exception cref="ArgumentNullException">
1064         /// The <paramref name="scheduler"/> argument is null.
1065         /// </exception>
1066         /// <exception cref="InvalidOperationException">
1067         /// The <see cref="Task"/> is not in a valid state to be started. It may have already been started,
1068         /// executed, or canceled, or it may have been created in a manner that doesn't support direct
1069         /// scheduling.
1070         /// </exception>
1071         public void Start(TaskScheduler scheduler)
1072         {
1073             // Read the volatile m_stateFlags field once and cache it for subsequent operations
1074             int flags = m_stateFlags;
1075
1076             // Need to check this before (m_action == null) because completed tasks will
1077             // set m_action to null.  We would want to know if this is the reason that m_action == null.
1078             if (IsCompletedMethod(flags))
1079             {
1080                 throw new InvalidOperationException(Environment.GetResourceString("Task_Start_TaskCompleted"));
1081             }
1082
1083             if (scheduler == null)
1084             {
1085                 throw new ArgumentNullException("scheduler");
1086             }
1087
1088             var options = OptionsMethod(flags);
1089             if ((options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0)
1090             {
1091                 throw new InvalidOperationException(Environment.GetResourceString("Task_Start_Promise"));
1092             }
1093             if ((options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) != 0)
1094             {
1095                 throw new InvalidOperationException(Environment.GetResourceString("Task_Start_ContinuationTask"));
1096             }
1097
1098             // Make sure that Task only gets started once.  Or else throw an exception.
1099             if (Interlocked.CompareExchange(ref m_taskScheduler, scheduler, null) != null)
1100             {
1101                 throw new InvalidOperationException(Environment.GetResourceString("Task_Start_AlreadyStarted"));
1102             }
1103
1104             ScheduleAndStart(true);
1105         }
1106
1107         /// <summary>
1108         /// Runs the <see cref="Task"/> synchronously on the current <see
1109         /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>.
1110         /// </summary>
1111         /// <remarks>
1112         /// <para>
1113         /// A task may only be started and run only once. Any attempts to schedule a task a second time will
1114         /// result in an exception.
1115         /// </para>
1116         /// <para>
1117         /// Tasks executed with <see cref="RunSynchronously()"/> will be associated with the current <see
1118         /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>.
1119         /// </para>
1120         /// <para>
1121         /// If the target scheduler does not support running this Task on the current thread, the Task will
1122         /// be scheduled for execution on the scheduler, and the current thread will block until the
1123         /// Task has completed execution.
1124         /// </para>
1125         /// </remarks>
1126         /// <exception cref="InvalidOperationException">
1127         /// The <see cref="Task"/> is not in a valid state to be started. It may have already been started,
1128         /// executed, or canceled, or it may have been created in a manner that doesn't support direct
1129         /// scheduling.
1130         /// </exception>
1131         public void RunSynchronously()
1132         {
1133             InternalRunSynchronously(TaskScheduler.Current, waitForCompletion: true);
1134         }
1135
1136         /// <summary>
1137         /// Runs the <see cref="Task"/> synchronously on the <see
1138         /// cref="System.Threading.Tasks.TaskScheduler">scheduler</see> provided.
1139         /// </summary>
1140         /// <remarks>
1141         /// <para>
1142         /// A task may only be started and run only once. Any attempts to schedule a task a second time will
1143         /// result in an exception.
1144         /// </para>
1145         /// <para>
1146         /// If the target scheduler does not support running this Task on the current thread, the Task will
1147         /// be scheduled for execution on the scheduler, and the current thread will block until the
1148         /// Task has completed execution.
1149         /// </para>
1150         /// </remarks>
1151         /// <exception cref="InvalidOperationException">
1152         /// The <see cref="Task"/> is not in a valid state to be started. It may have already been started,
1153         /// executed, or canceled, or it may have been created in a manner that doesn't support direct
1154         /// scheduling.
1155         /// </exception>
1156         /// <exception cref="ArgumentNullException">The <paramref name="scheduler"/> parameter
1157         /// is null.</exception>
1158         /// <param name="scheduler">The scheduler on which to attempt to run this task inline.</param>
1159         public void RunSynchronously(TaskScheduler scheduler)
1160         {
1161             if (scheduler == null)
1162             {
1163                 throw new ArgumentNullException("scheduler");
1164             }
1165             Contract.EndContractBlock();
1166
1167             InternalRunSynchronously(scheduler, waitForCompletion: true);
1168         }
1169
1170         //
1171         // Internal version of RunSynchronously that allows not waiting for completion.
1172         // 
1173         [SecuritySafeCritical] // Needed for QueueTask
1174         internal void InternalRunSynchronously(TaskScheduler scheduler, bool waitForCompletion)
1175         {
1176             Contract.Requires(scheduler != null, "Task.InternalRunSynchronously(): null TaskScheduler");
1177
1178             // Read the volatile m_stateFlags field once and cache it for subsequent operations
1179             int flags = m_stateFlags;
1180
1181             // Can't call this method on a continuation task
1182             var options = OptionsMethod(flags);
1183             if ((options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) != 0)
1184             {
1185                 throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_Continuation"));
1186             }
1187
1188             // Can't call this method on a promise-style task
1189             if ((options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0)
1190             {
1191                 throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_Promise"));
1192             }
1193
1194             // Can't call this method on a task that has already completed
1195             if (IsCompletedMethod(flags))
1196             {
1197                 throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_TaskCompleted"));
1198             }
1199
1200             // Make sure that Task only gets started once.  Or else throw an exception.
1201             if (Interlocked.CompareExchange(ref m_taskScheduler, scheduler, null) != null)
1202             {
1203                 throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_AlreadyStarted"));
1204             }
1205
1206             // execute only if we win the ---- against concurrent cancel attempts.
1207             // otherwise throw an exception, because we've been canceled.
1208             if (MarkStarted())
1209             {
1210                 bool taskQueued = false;
1211                 try
1212                 {
1213                     // We wrap TryRunInline() in a try/catch block and move an excepted task to Faulted here,
1214                     // but not in Wait()/WaitAll()/FastWaitAll().  Here, we know for sure that the
1215                     // task will not be subsequently scheduled (assuming that the scheduler adheres
1216                     // to the guideline that an exception implies that no state change took place),
1217                     // so it is safe to catch the exception and move the task to a final state.  The
1218                     // same cannot be said for Wait()/WaitAll()/FastWaitAll().
1219                     if (!scheduler.TryRunInline(this, false))
1220                     {
1221                         scheduler.InternalQueueTask(this);
1222                         taskQueued = true; // only mark this after successfully queuing the task.
1223                     }
1224
1225                     // A successful TryRunInline doesn't guarantee completion, as there may be unfinished children.
1226                     // Also if we queued the task above, the task may not be done yet.
1227                     if (waitForCompletion && !IsCompleted)
1228                     {
1229                         SpinThenBlockingWait(Timeout.Infinite, default(CancellationToken));
1230                     }
1231                 }
1232                 catch (Exception e)
1233                 {
1234                     // we 1) either received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown
1235                     //    2) or a a ThreadAbortException, which we need to skip here, because it would already have been handled in Task.Execute
1236                     if (!taskQueued && !(e is ThreadAbortException))
1237                     {
1238                         // We had a problem with TryRunInline() or QueueTask().  
1239                         // Record the exception, marking ourselves as Completed/Faulted.
1240                         TaskSchedulerException tse = new TaskSchedulerException(e);
1241                         AddException(tse);
1242                         Finish(false);
1243
1244                         // Mark ourselves as "handled" to avoid crashing the finalizer thread if the caller neglects to
1245                         // call Wait() on this task.
1246                         // m_contingentProperties.m_exceptionsHolder *should* already exist after AddException()
1247                         Contract.Assert(
1248                             (m_contingentProperties != null) &&
1249                             (m_contingentProperties.m_exceptionsHolder != null) &&
1250                             (m_contingentProperties.m_exceptionsHolder.ContainsFaultList),
1251                             "Task.InternalRunSynchronously(): Expected m_contingentProperties.m_exceptionsHolder to exist " +
1252                             "and to have faults recorded.");
1253                         m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false);
1254
1255                         // And re-throw.
1256                         throw tse;
1257                     }
1258                     // We had a problem with waiting or this is a thread abort.  Just re-throw.
1259                     else throw;
1260                 }
1261             }
1262             else
1263             {
1264                 Contract.Assert((m_stateFlags & TASK_STATE_CANCELED) != 0, "Task.RunSynchronously: expected TASK_STATE_CANCELED to be set");
1265                 // Can't call this method on canceled task.
1266                 throw new InvalidOperationException(Environment.GetResourceString("Task_RunSynchronously_TaskCompleted"));
1267             }
1268         }
1269
1270
1271         ////
1272         //// Helper methods for Factory StartNew methods.
1273         ////
1274
1275
1276         // Implicitly converts action to object and handles the meat of the StartNew() logic.
1277         internal static Task InternalStartNew(
1278             Task creatingTask, Delegate action, object state, CancellationToken cancellationToken, TaskScheduler scheduler,
1279             TaskCreationOptions options, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark)
1280         {
1281             // Validate arguments.
1282             if (scheduler == null)
1283             {
1284                 throw new ArgumentNullException("scheduler");
1285             }
1286             Contract.EndContractBlock();
1287
1288             // Create and schedule the task. This throws an InvalidOperationException if already shut down.
1289             // Here we add the InternalTaskOptions.QueuedByRuntime to the internalOptions, so that TaskConstructorCore can skip the cancellation token registration
1290             Task t = new Task(action, state, creatingTask, cancellationToken, options, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
1291             t.PossiblyCaptureContext(ref stackMark);
1292
1293             t.ScheduleAndStart(false);
1294             return t;
1295         }
1296
1297         /// <summary>
1298         /// Gets a unique ID for a <see cref="Task">Task</see> or task continuation instance.
1299         /// </summary>
1300         internal static int NewId()
1301         {
1302             int newId = 0;
1303             // We need to repeat if Interlocked.Increment wraps around and returns 0.
1304             // Otherwise next time this task's Id is queried it will get a new value
1305             do
1306             {
1307                 newId = Interlocked.Increment(ref s_taskIdCounter);
1308             }
1309             while (newId == 0);
1310             TplEtwProvider.Log.NewID(newId);
1311             return newId;
1312         }
1313
1314
1315         /////////////
1316         // properties
1317
1318         /// <summary>
1319         /// Gets a unique ID for this <see cref="Task">Task</see> instance.
1320         /// </summary>
1321         /// <remarks>
1322         /// Task IDs are assigned on-demand and do not necessarily represent the order in the which Task
1323         /// instances were created.
1324         /// </remarks>
1325         public int Id
1326         {
1327             get
1328             {
1329                 if (m_taskId == 0)
1330                 {
1331                     int newId = NewId();
1332                     Interlocked.CompareExchange(ref m_taskId, newId, 0);
1333                 }
1334
1335                 return m_taskId;
1336             }
1337         }
1338
1339         /// <summary>
1340         /// Returns the unique ID of the currently executing <see cref="Task">Task</see>.
1341         /// </summary>
1342         public static int? CurrentId
1343         {
1344             get
1345             {
1346                 Task currentTask = InternalCurrent;
1347                 if (currentTask != null)
1348                     return currentTask.Id;
1349                 else
1350                     return null;
1351             }
1352         }
1353
1354         /// <summary>
1355         /// Gets the <see cref="Task">Task</see> instance currently executing, or
1356         /// null if none exists.
1357         /// </summary>
1358         internal static Task InternalCurrent
1359         {
1360             get { return t_currentTask; }
1361         }
1362
1363         /// <summary>
1364         /// Gets the Task instance currently executing if the specified creation options
1365         /// contain AttachedToParent.
1366         /// </summary>
1367         /// <param name="options">The options to check.</param>
1368         /// <returns>The current task if there is one and if AttachToParent is in the options; otherwise, null.</returns>
1369         internal static Task InternalCurrentIfAttached(TaskCreationOptions creationOptions)
1370         {
1371             return (creationOptions & TaskCreationOptions.AttachedToParent) != 0 ? InternalCurrent : null;
1372         }
1373
1374         /// <summary>
1375         /// Gets the StackGuard object assigned to the current thread.
1376         /// </summary>
1377         internal static StackGuard CurrentStackGuard
1378         {
1379             get
1380             {
1381                 StackGuard sg = t_stackGuard;
1382                 if (sg == null)
1383                 {
1384                     t_stackGuard = sg = new StackGuard();
1385                 }
1386                 return sg;
1387             }
1388         }
1389
1390
1391         /// <summary>
1392         /// Gets the <see cref="T:System.AggregateException">Exception</see> that caused the <see
1393         /// cref="Task">Task</see> to end prematurely. If the <see
1394         /// cref="Task">Task</see> completed successfully or has not yet thrown any
1395         /// exceptions, this will return null.
1396         /// </summary>
1397         /// <remarks>
1398         /// Tasks that throw unhandled exceptions store the resulting exception and propagate it wrapped in a
1399         /// <see cref="System.AggregateException"/> in calls to <see cref="Wait()">Wait</see>
1400         /// or in accesses to the <see cref="Exception"/> property.  Any exceptions not observed by the time
1401         /// the Task instance is garbage collected will be propagated on the finalizer thread.
1402         /// </remarks>
1403         public AggregateException Exception
1404         {
1405             get
1406             {
1407                 AggregateException e = null;
1408
1409                 // If you're faulted, retrieve the exception(s)
1410                 if (IsFaulted) e = GetExceptions(false);
1411
1412                 // Only return an exception in faulted state (skip manufactured exceptions)
1413                 // A "benevolent" race condition makes it possible to return null when IsFaulted is
1414                 // true (i.e., if IsFaulted is set just after the check to IsFaulted above).
1415                 Contract.Assert((e == null) || IsFaulted, "Task.Exception_get(): returning non-null value when not Faulted");
1416
1417                 return e;
1418             }
1419         }
1420
1421         /// <summary>
1422         /// Gets the <see cref="T:System.Threading.Tasks.TaskStatus">TaskStatus</see> of this Task. 
1423         /// </summary>
1424         public TaskStatus Status
1425         {
1426             get
1427             {
1428                 TaskStatus rval;
1429
1430                 // get a cached copy of the state flags.  This should help us
1431                 // to get a consistent view of the flags if they are changing during the
1432                 // execution of this method.
1433                 int sf = m_stateFlags;
1434
1435                 if ((sf & TASK_STATE_FAULTED) != 0) rval = TaskStatus.Faulted;
1436                 else if ((sf & TASK_STATE_CANCELED) != 0) rval = TaskStatus.Canceled;
1437                 else if ((sf & TASK_STATE_RAN_TO_COMPLETION) != 0) rval = TaskStatus.RanToCompletion;
1438                 else if ((sf & TASK_STATE_WAITING_ON_CHILDREN) != 0) rval = TaskStatus.WaitingForChildrenToComplete;
1439                 else if ((sf & TASK_STATE_DELEGATE_INVOKED) != 0) rval = TaskStatus.Running;
1440                 else if ((sf & TASK_STATE_STARTED) != 0) rval = TaskStatus.WaitingToRun;
1441                 else if ((sf & TASK_STATE_WAITINGFORACTIVATION) != 0) rval = TaskStatus.WaitingForActivation;
1442                 else rval = TaskStatus.Created;
1443
1444                 return rval;
1445             }
1446         }
1447
1448         /// <summary>
1449         /// Gets whether this <see cref="Task">Task</see> instance has completed
1450         /// execution due to being canceled.
1451         /// </summary>
1452         /// <remarks>
1453         /// A <see cref="Task">Task</see> will complete in Canceled state either if its <see cref="CancellationToken">CancellationToken</see> 
1454         /// was marked for cancellation before the task started executing, or if the task acknowledged the cancellation request on 
1455         /// its already signaled CancellationToken by throwing an 
1456         /// <see cref="System.OperationCanceledException">OperationCanceledException</see> that bears the same 
1457         /// <see cref="System.Threading.CancellationToken">CancellationToken</see>.
1458         /// </remarks>
1459         public bool IsCanceled
1460         {
1461             get
1462             {
1463                 // Return true if canceled bit is set and faulted bit is not set
1464                 return (m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_FAULTED)) == TASK_STATE_CANCELED;
1465             }
1466         }
1467
1468         /// <summary>
1469         /// Returns true if this task has a cancellation token and it was signaled.
1470         /// To be used internally in execute entry codepaths.
1471         /// </summary>
1472         internal bool IsCancellationRequested
1473         {
1474             get
1475             {
1476                 // check both the internal cancellation request flag and the CancellationToken attached to this task
1477                 var props = m_contingentProperties;
1478                 return props != null &&
1479                     (props.m_internalCancellationRequested == CANCELLATION_REQUESTED ||
1480                      props.m_cancellationToken.IsCancellationRequested);
1481             }
1482         }
1483
1484         /// <summary>
1485         /// Ensures that the contingent properties field has been initialized.
1486         /// ASSUMES THAT m_stateFlags IS ALREADY SET!
1487         /// </summary>
1488         /// <param name="needsProtection">true if this needs to be done in a thread-safe manner; otherwise, false.</param>
1489         /// <returns>The initialized contingent properties object.</returns>
1490         internal ContingentProperties EnsureContingentPropertiesInitialized(bool needsProtection)
1491         {
1492             var props = m_contingentProperties;
1493             return props != null ? props : EnsureContingentPropertiesInitializedCore(needsProtection);
1494         }
1495
1496         /// <summary>
1497         /// Initializes the contingent properties object.  This assumes a check has already been done for nullness.
1498         /// </summary>
1499         /// <param name="needsProtection">true if this needs to be done in a thread-safe manner; otherwise, false.</param>
1500         /// <returns>The initialized contingent properties object.</returns>
1501         private ContingentProperties EnsureContingentPropertiesInitializedCore(bool needsProtection)
1502         {
1503             if (needsProtection)
1504             {
1505                 return LazyInitializer.EnsureInitialized<ContingentProperties>(ref m_contingentProperties, s_createContingentProperties);
1506             }
1507             else
1508             {
1509                 Contract.Assert(m_contingentProperties == null, "Expected props to be null after checking and with needsProtection == false");
1510                 return m_contingentProperties = new ContingentProperties();
1511             }
1512         }
1513
1514         // Cached functions for lazily initializing contingent properties
1515         private static readonly Func<ContingentProperties> s_createContingentProperties = () => new ContingentProperties();
1516
1517         /// <summary>
1518         /// This internal property provides access to the CancellationToken that was set on the task 
1519         /// when it was constructed.
1520         /// </summary>
1521         internal CancellationToken CancellationToken
1522         {
1523             get
1524             {
1525                 var props = m_contingentProperties;
1526                 return (props == null) ? default(CancellationToken) : props.m_cancellationToken;
1527             }
1528         }
1529
1530         /// <summary>
1531         /// Gets whether this <see cref="Task"/> threw an OperationCanceledException while its CancellationToken was signaled.
1532         /// </summary>
1533         internal bool IsCancellationAcknowledged
1534         {
1535             get { return (m_stateFlags & TASK_STATE_CANCELLATIONACKNOWLEDGED) != 0; }
1536         }
1537
1538
1539         /// <summary>
1540         /// Gets whether this <see cref="Task">Task</see> has completed.
1541         /// </summary>
1542         /// <remarks>
1543         /// <see cref="IsCompleted"/> will return true when the Task is in one of the three
1544         /// final states: <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
1545         /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
1546         /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
1547         /// </remarks>
1548         public bool IsCompleted
1549         {
1550             get
1551             {
1552                 int stateFlags = m_stateFlags; // enable inlining of IsCompletedMethod by "cast"ing away the volatility
1553                 return IsCompletedMethod(stateFlags);
1554             }
1555         }
1556
1557         // Similar to IsCompleted property, but allows for the use of a cached flags value
1558         // rather than reading the volatile m_stateFlags field.
1559         private static bool IsCompletedMethod(int flags)
1560         {
1561             return (flags & TASK_STATE_COMPLETED_MASK) != 0;
1562         }
1563
1564         // For use in InternalWait -- marginally faster than (Task.Status == TaskStatus.RanToCompletion)
1565         internal bool IsRanToCompletion
1566         {
1567             get { return (m_stateFlags & TASK_STATE_COMPLETED_MASK) == TASK_STATE_RAN_TO_COMPLETION; }
1568         }
1569
1570         /// <summary>
1571         /// Gets the <see cref="T:System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used
1572         /// to create this task.
1573         /// </summary>
1574         public TaskCreationOptions CreationOptions
1575         {
1576             get { return Options & (TaskCreationOptions)(~InternalTaskOptions.InternalOptionsMask); }
1577         }
1578
1579         /// <summary>
1580         /// Gets a <see cref="T:System.Threading.WaitHandle"/> that can be used to wait for the task to
1581         /// complete.
1582         /// </summary>
1583         /// <remarks>
1584         /// Using the wait functionality provided by <see cref="Wait()"/>
1585         /// should be preferred over using <see cref="IAsyncResult.AsyncWaitHandle"/> for similar
1586         /// functionality.
1587         /// </remarks>
1588         /// <exception cref="T:System.ObjectDisposedException">
1589         /// The <see cref="Task"/> has been disposed.
1590         /// </exception>
1591         WaitHandle IAsyncResult.AsyncWaitHandle
1592         {
1593             // Although a slim event is used internally to avoid kernel resource allocation, this function
1594             // forces allocation of a true WaitHandle when called.
1595             get
1596             {
1597                 bool isDisposed = (m_stateFlags & TASK_STATE_DISPOSED) != 0;
1598                 if (isDisposed)
1599                 {
1600                     throw new ObjectDisposedException(null, Environment.GetResourceString("Task_ThrowIfDisposed"));
1601                 }
1602                 return CompletedEvent.WaitHandle;
1603             }
1604         }
1605
1606         /// <summary>
1607         /// Gets the state object supplied when the <see cref="Task">Task</see> was created,
1608         /// or null if none was supplied.
1609         /// </summary>
1610         public object AsyncState
1611         {
1612             get { return m_stateObject; }
1613         }
1614
1615         /// <summary>
1616         /// Gets an indication of whether the asynchronous operation completed synchronously.
1617         /// </summary>
1618         /// <value>true if the asynchronous operation completed synchronously; otherwise, false.</value>
1619         bool IAsyncResult.CompletedSynchronously
1620         {
1621             get
1622             {
1623                 return false;
1624             }
1625         }
1626
1627         /// <summary>
1628         /// Provides access to the TaskScheduler responsible for executing this Task.
1629         /// </summary>
1630         internal TaskScheduler ExecutingTaskScheduler
1631         {
1632             get { return m_taskScheduler; }
1633         }
1634
1635         /// <summary>
1636         /// Provides access to factory methods for creating <see cref="Task"/> and <see cref="Task{TResult}"/> instances.
1637         /// </summary>
1638         /// <remarks>
1639         /// The factory returned from <see cref="Factory"/> is a default instance
1640         /// of <see cref="System.Threading.Tasks.TaskFactory"/>, as would result from using
1641         /// the default constructor on TaskFactory.
1642         /// </remarks>
1643         public static TaskFactory Factory { get { return s_factory; } }
1644
1645         /// <summary>A task that's already been completed successfully.</summary>
1646         private static Task s_completedTask;
1647
1648         /// <summary>Gets a task that's already been completed successfully.</summary>
1649         /// <remarks>May not always return the same instance.</remarks>        
1650         public static Task CompletedTask
1651         {
1652             get
1653             {
1654                 var completedTask = s_completedTask;
1655                 if (completedTask == null)
1656                     s_completedTask = completedTask = new Task(false, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken)); // benign initialization ----
1657                 return completedTask;
1658             }
1659         }
1660
1661         /// <summary>
1662         /// Provides an event that can be used to wait for completion.
1663         /// Only called by IAsyncResult.AsyncWaitHandle, which means that we really do need to instantiate a completion event.
1664         /// </summary>
1665         internal ManualResetEventSlim CompletedEvent
1666         {
1667             get
1668             {
1669                 var contingentProps = EnsureContingentPropertiesInitialized(needsProtection: true);
1670                 if (contingentProps.m_completionEvent == null)
1671                 {
1672                     bool wasCompleted = IsCompleted;
1673                     ManualResetEventSlim newMre = new ManualResetEventSlim(wasCompleted);
1674                     if (Interlocked.CompareExchange(ref contingentProps.m_completionEvent, newMre, null) != null)
1675                     {
1676                         // We lost the ----, so we will just close the event right away.
1677                         newMre.Dispose();
1678                     }
1679                     else if (!wasCompleted && IsCompleted)
1680                     {
1681                         // We published the event as unset, but the task has subsequently completed.
1682                         // Set the event's state properly so that callers don't deadlock.
1683                         newMre.Set();
1684                     }
1685                 }
1686
1687                 return contingentProps.m_completionEvent;
1688             }
1689         }
1690
1691         /// <summary>
1692         /// Determines whether this is the root task of a self replicating group.
1693         /// </summary>
1694         internal bool IsSelfReplicatingRoot
1695         {
1696             get
1697             {
1698                 // Return true if self-replicating bit is set and child replica bit is not set
1699                 return (Options & (TaskCreationOptions)(InternalTaskOptions.SelfReplicating | InternalTaskOptions.ChildReplica))
1700                     == (TaskCreationOptions)InternalTaskOptions.SelfReplicating;
1701             }
1702         }
1703
1704         /// <summary>
1705         /// Determines whether the task is a replica itself.
1706         /// </summary>
1707         internal bool IsChildReplica
1708         {
1709             get { return (Options & (TaskCreationOptions)InternalTaskOptions.ChildReplica) != 0; }
1710         }
1711
1712         internal int ActiveChildCount
1713         {
1714             get
1715             {
1716                 var props = m_contingentProperties;
1717                 return props != null ? props.m_completionCountdown - 1 : 0;
1718             }
1719         }
1720
1721         /// <summary>
1722         /// The property formerly known as IsFaulted.
1723         /// </summary>
1724         internal bool ExceptionRecorded
1725         {
1726             get
1727             {
1728                 var props = m_contingentProperties;
1729                 return (props != null) && (props.m_exceptionsHolder != null) && (props.m_exceptionsHolder.ContainsFaultList);
1730             }
1731         }
1732
1733         /// <summary>
1734         /// Gets whether the <see cref="Task"/> completed due to an unhandled exception.
1735         /// </summary>
1736         /// <remarks>
1737         /// If <see cref="IsFaulted"/> is true, the Task's <see cref="Status"/> will be equal to
1738         /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">TaskStatus.Faulted</see>, and its
1739         /// <see cref="Exception"/> property will be non-null.
1740         /// </remarks>
1741         public bool IsFaulted
1742         {
1743             get
1744             {
1745                 // Faulted is "king" -- if that bit is present (regardless of other bits), we are faulted.
1746                 return ((m_stateFlags & TASK_STATE_FAULTED) != 0);
1747             }
1748         }
1749
1750         /// <summary>
1751         /// The captured execution context for the current task to run inside
1752         /// If the TASK_STATE_EXECUTIONCONTEXT_IS_NULL flag is set, this means ExecutionContext.Capture returned null, otherwise
1753         /// If the captured context is the default, nothing is saved, otherwise the m_contingentProperties inflates to save the context
1754         /// </summary>
1755         internal ExecutionContext CapturedContext
1756         {
1757             get
1758             {
1759                 if ((m_stateFlags & TASK_STATE_EXECUTIONCONTEXT_IS_NULL) == TASK_STATE_EXECUTIONCONTEXT_IS_NULL)
1760                 {
1761                     return null;
1762                 }
1763                 else
1764                 {
1765                     var props = m_contingentProperties;
1766                     if (props != null && props.m_capturedContext != null) return props.m_capturedContext;
1767                     else return ExecutionContext.PreAllocatedDefault;
1768                 }
1769             }
1770             set
1771             {
1772                 // There is no need to atomically set this bit because this set() method is only called during construction, and therefore there should be no contending accesses to m_stateFlags
1773                 if (value == null)
1774                 {
1775                     m_stateFlags |= TASK_STATE_EXECUTIONCONTEXT_IS_NULL;
1776                 }
1777                 else if (!value.IsPreAllocatedDefault) // not the default context, then inflate the contingent properties and set it
1778                 {
1779                     EnsureContingentPropertiesInitialized(needsProtection: false).m_capturedContext = value;
1780                 }
1781                 //else do nothing, this is the default context
1782             }
1783         }
1784
1785         /// <summary>
1786         /// Static helper function to copy specific ExecutionContext
1787         /// </summary>
1788         /// <param name="capturedContext">The captured context</param>
1789         /// <returns>The copied context, null if the capturedContext is null</returns>
1790         private static ExecutionContext CopyExecutionContext(ExecutionContext capturedContext)
1791         {
1792             if (capturedContext == null)
1793                 return null;
1794             if (capturedContext.IsPreAllocatedDefault)
1795                 return ExecutionContext.PreAllocatedDefault;
1796
1797             return capturedContext.CreateCopy();
1798         }
1799
1800
1801 #if DEBUG
1802         /// <summary>
1803         /// Retrieves an identifier for the task.
1804         /// </summary>
1805         internal int InternalId
1806         {
1807             get { return GetHashCode(); }
1808         }
1809 #endif
1810
1811         /////////////
1812         // methods
1813
1814
1815         /// <summary>
1816         /// Disposes the <see cref="Task"/>, releasing all of its unmanaged resources.  
1817         /// </summary>
1818         /// <remarks>
1819         /// Unlike most of the members of <see cref="Task"/>, this method is not thread-safe.
1820         /// Also, <see cref="Dispose()"/> may only be called on a <see cref="Task"/> that is in one of
1821         /// the final states: <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
1822         /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
1823         /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
1824         /// </remarks>
1825         /// <exception cref="T:System.InvalidOperationException">
1826         /// The exception that is thrown if the <see cref="Task"/> is not in 
1827         /// one of the final states: <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
1828         /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
1829         /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
1830         /// </exception>        
1831         public void Dispose()
1832         {
1833             Dispose(true);
1834             GC.SuppressFinalize(this);
1835         }
1836
1837         /// <summary>
1838         /// Disposes the <see cref="Task"/>, releasing all of its unmanaged resources.  
1839         /// </summary>
1840         /// <param name="disposing">
1841         /// A Boolean value that indicates whether this method is being called due to a call to <see
1842         /// cref="Dispose()"/>.
1843         /// </param>
1844         /// <remarks>
1845         /// Unlike most of the members of <see cref="Task"/>, this method is not thread-safe.
1846         /// </remarks>
1847         protected virtual void Dispose(bool disposing)
1848         {
1849             if (disposing)
1850             {
1851                 // Dispose is a nop if this task was created with the DoNotDispose internal option.
1852                 // This is done before the completed check, because if we're not touching any 
1853                 // state on the task, it's ok for it to happen before completion.
1854                 if ((Options & (TaskCreationOptions)InternalTaskOptions.DoNotDispose) != 0)
1855                 {
1856                     return;
1857                 }
1858
1859                 // Task must be completed to dispose
1860                 if (!IsCompleted)
1861                 {
1862                     throw new InvalidOperationException(Environment.GetResourceString("Task_Dispose_NotCompleted"));
1863                 }
1864
1865                 // Dispose of the underlying completion event if it exists
1866                 var cp = m_contingentProperties;
1867                 if (cp != null)
1868                 {
1869                     // Make a copy to protect against racing Disposes.
1870                     // If we wanted to make this a bit safer, we could use an interlocked here,
1871                     // but we state that Dispose is not thread safe.
1872                     var ev = cp.m_completionEvent;
1873                     if (ev != null)
1874                     {
1875                         // Null out the completion event in contingent props; we'll use our copy from here on out
1876                         cp.m_completionEvent = null;
1877
1878                         // In the unlikely event that our completion event is inflated but not yet signaled,
1879                         // go ahead and signal the event.  If you dispose of an unsignaled MRES, then any waiters
1880                         // will deadlock; an ensuing Set() will not wake them up.  In the event of an AppDomainUnload,
1881                         // there is no guarantee that anyone else is going to signal the event, and it does no harm to 
1882                         // call Set() twice on m_completionEvent.
1883                         if (!ev.IsSet) ev.Set();
1884
1885                         // Finally, dispose of the event
1886                         ev.Dispose();
1887                     }
1888                 }
1889             }
1890
1891             // We OR the flags to indicate the object has been disposed. The task
1892             // has already completed at this point, and the only conceivable ---- would
1893             // be with the unsetting of the TASK_STATE_WAIT_COMPLETION_NOTIFICATION flag, which
1894             // ---- is extremely unlikely and also benign.  (Worst case: we hit a breakpoint
1895             // twice instead of once in the debugger.  Weird, but not lethal.)
1896             m_stateFlags |= TASK_STATE_DISPOSED;
1897         }
1898
1899         /////////////
1900         // internal helpers
1901
1902
1903         /// <summary>
1904         /// Schedules the task for execution.
1905         /// </summary>
1906         /// <param name="needsProtection">If true, TASK_STATE_STARTED bit is turned on in
1907         /// an atomic fashion, making sure that TASK_STATE_CANCELED does not get set
1908         /// underneath us.  If false, TASK_STATE_STARTED bit is OR-ed right in.  This
1909         /// allows us to streamline things a bit for StartNew(), where competing cancellations
1910         /// are not a problem.</param>
1911         [SecuritySafeCritical] // Needed for QueueTask
1912         internal void ScheduleAndStart(bool needsProtection)
1913         {
1914             Contract.Assert(m_taskScheduler != null, "expected a task scheduler to have been selected");
1915             Contract.Assert((m_stateFlags & TASK_STATE_STARTED) == 0, "task has already started");
1916
1917             // Set the TASK_STATE_STARTED bit
1918             if (needsProtection)
1919             {
1920                 if (!MarkStarted())
1921                 {
1922                     // A cancel has snuck in before we could get started.  Quietly exit.
1923                     return;
1924                 }
1925             }
1926             else
1927             {
1928                 m_stateFlags |= TASK_STATE_STARTED;
1929             }
1930
1931             if (s_asyncDebuggingEnabled)
1932             {
1933                 AddToActiveTasks(this);
1934             }
1935
1936             if (AsyncCausalityTracer.LoggingOn && (Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0)
1937             {
1938                 //For all other task than TaskContinuations we want to log. TaskContinuations log in their constructor
1939                 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task: "+((Delegate)m_action).Method.Name, 0);
1940             }
1941
1942
1943             try
1944             {
1945                 // Queue to the indicated scheduler.
1946                 m_taskScheduler.InternalQueueTask(this);
1947             }
1948             catch (ThreadAbortException tae)
1949             {
1950                 AddException(tae);
1951                 FinishThreadAbortedTask(true, false);
1952             }
1953             catch (Exception e)
1954             {
1955                 // The scheduler had a problem queueing this task.  Record the exception, leaving this task in
1956                 // a Faulted state.
1957                 TaskSchedulerException tse = new TaskSchedulerException(e);
1958                 AddException(tse);
1959                 Finish(false);
1960
1961                 // Now we need to mark ourselves as "handled" to avoid crashing the finalizer thread if we are called from StartNew()
1962                 // or from the self replicating logic, because in both cases the exception is either propagated outside directly, or added
1963                 // to an enclosing parent. However we won't do this for continuation tasks, because in that case we internally eat the exception
1964                 // and therefore we need to make sure the user does later observe it explicitly or see it on the finalizer.
1965
1966                 if ((Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0)
1967                 {
1968                     // m_contingentProperties.m_exceptionsHolder *should* already exist after AddException()
1969                     Contract.Assert(
1970                         (m_contingentProperties != null) &&
1971                         (m_contingentProperties.m_exceptionsHolder != null) &&
1972                         (m_contingentProperties.m_exceptionsHolder.ContainsFaultList),
1973                             "Task.ScheduleAndStart(): Expected m_contingentProperties.m_exceptionsHolder to exist " +
1974                             "and to have faults recorded.");
1975
1976                     m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false);
1977                 }
1978                 // re-throw the exception wrapped as a TaskSchedulerException.
1979                 throw tse;
1980             }
1981         }
1982
1983         /// <summary>
1984         /// Adds an exception to the list of exceptions this task has thrown.
1985         /// </summary>
1986         /// <param name="exceptionObject">An object representing either an Exception or a collection of Exceptions.</param>
1987         internal void AddException(object exceptionObject)
1988         {
1989             Contract.Requires(exceptionObject != null, "Task.AddException: Expected a non-null exception object");
1990             AddException(exceptionObject, representsCancellation: false);
1991         }
1992
1993         /// <summary>
1994         /// Adds an exception to the list of exceptions this task has thrown.
1995         /// </summary>
1996         /// <param name="exceptionObject">An object representing either an Exception or a collection of Exceptions.</param>
1997         /// <param name="representsCancellation">Whether the exceptionObject is an OperationCanceledException representing cancellation.</param>
1998         internal void AddException(object exceptionObject, bool representsCancellation)
1999         {
2000             Contract.Requires(exceptionObject != null, "Task.AddException: Expected a non-null exception object");
2001
2002 #if DEBUG
2003             var eoAsException = exceptionObject as Exception;
2004             var eoAsEnumerableException = exceptionObject as IEnumerable<Exception>;
2005             var eoAsEdi = exceptionObject as ExceptionDispatchInfo;
2006             var eoAsEnumerableEdi = exceptionObject as IEnumerable<ExceptionDispatchInfo>;
2007
2008             Contract.Assert(
2009                 eoAsException != null || eoAsEnumerableException != null || eoAsEdi != null || eoAsEnumerableEdi != null,
2010                 "Task.AddException: Expected an Exception, ExceptionDispatchInfo, or an IEnumerable<> of one of those");
2011
2012             var eoAsOce = exceptionObject as OperationCanceledException;
2013
2014             Contract.Assert(
2015                 !representsCancellation ||
2016                 eoAsOce != null ||
2017                 (eoAsEdi != null && eoAsEdi.SourceException is OperationCanceledException),
2018                 "representsCancellation should be true only if an OCE was provided.");
2019 #endif
2020
2021             //
2022             // WARNING: A great deal of care went into ensuring that
2023             // AddException() and GetExceptions() are never called
2024             // simultaneously.  See comment at start of GetExceptions().
2025             //
2026
2027             // Lazily initialize the holder, ensuring only one thread wins.
2028             var props = EnsureContingentPropertiesInitialized(needsProtection: true);
2029             if (props.m_exceptionsHolder == null)
2030             {
2031                 TaskExceptionHolder holder = new TaskExceptionHolder(this);
2032                 if (Interlocked.CompareExchange(ref props.m_exceptionsHolder, holder, null) != null)
2033                 {
2034                     // If we lost the ----, suppress finalization.
2035                     holder.MarkAsHandled(false);
2036                 }
2037             }
2038
2039             lock (props)
2040             {
2041                 props.m_exceptionsHolder.Add(exceptionObject, representsCancellation);
2042             }
2043         }
2044
2045         /// <summary>
2046         /// Returns a list of exceptions by aggregating the holder's contents. Or null if
2047         /// no exceptions have been thrown.
2048         /// </summary>
2049         /// <param name="includeTaskCanceledExceptions">Whether to include a TCE if cancelled.</param>
2050         /// <returns>An aggregate exception, or null if no exceptions have been caught.</returns>
2051         private AggregateException GetExceptions(bool includeTaskCanceledExceptions)
2052         {
2053             //
2054             // WARNING: The Task/Task<TResult>/TaskCompletionSource classes
2055             // have all been carefully crafted to insure that GetExceptions()
2056             // is never called while AddException() is being called.  There
2057             // are locks taken on m_contingentProperties in several places:
2058             //
2059             // -- Task<TResult>.TrySetException(): The lock allows the
2060             //    task to be set to Faulted state, and all exceptions to
2061             //    be recorded, in one atomic action.  
2062             //
2063             // -- Task.Exception_get(): The lock ensures that Task<TResult>.TrySetException()
2064             //    is allowed to complete its operation before Task.Exception_get()
2065             //    can access GetExceptions().
2066             //
2067             // -- Task.ThrowIfExceptional(): The lock insures that Wait() will
2068             //    not attempt to call GetExceptions() while Task<TResult>.TrySetException()
2069             //    is in the process of calling AddException().
2070             //
2071             // For "regular" tasks, we effectively keep AddException() and GetException()
2072             // from being called concurrently by the way that the state flows.  Until
2073             // a Task is marked Faulted, Task.Exception_get() returns null.  And
2074             // a Task is not marked Faulted until it and all of its children have
2075             // completed, which means that all exceptions have been recorded.
2076             //
2077             // It might be a lot easier to follow all of this if we just required
2078             // that all calls to GetExceptions() and AddExceptions() were made
2079             // under a lock on m_contingentProperties.  But that would also
2080             // increase our lock occupancy time and the frequency with which we
2081             // would need to take the lock.
2082             //
2083             // If you add a call to GetExceptions() anywhere in the code,
2084             // please continue to maintain the invariant that it can't be
2085             // called when AddException() is being called.
2086             //
2087
2088             // We'll lazily create a TCE if the task has been canceled.
2089             Exception canceledException = null;
2090             if (includeTaskCanceledExceptions && IsCanceled)
2091             {
2092                 // Backcompat: 
2093                 // Ideally we'd just use the cached OCE from this.GetCancellationExceptionDispatchInfo()
2094                 // here.  However, that would result in a potentially breaking change from .NET 4, which
2095                 // has the code here that throws a new exception instead of the original, and the EDI
2096                 // may not contain a TCE, but an OCE or any OCE-derived type, which would mean we'd be
2097                 // propagating an exception of a different type.
2098                 canceledException = new TaskCanceledException(this);
2099             }
2100
2101             if (ExceptionRecorded)
2102             {
2103                 // There are exceptions; get the aggregate and optionally add the canceled
2104                 // exception to the aggregate (if applicable).
2105                 Contract.Assert(m_contingentProperties != null); // ExceptionRecorded ==> m_contingentProperties != null
2106
2107                 // No need to lock around this, as other logic prevents the consumption of exceptions
2108                 // before they have been completely processed.
2109                 return m_contingentProperties.m_exceptionsHolder.CreateExceptionObject(false, canceledException);
2110             }
2111             else if (canceledException != null)
2112             {
2113                 // No exceptions, but there was a cancelation. Aggregate and return it.
2114                 return new AggregateException(canceledException);
2115             }
2116
2117             return null;
2118         }
2119
2120         /// <summary>Gets the exception dispatch infos once the task has faulted.</summary>
2121         internal ReadOnlyCollection<ExceptionDispatchInfo> GetExceptionDispatchInfos()
2122         {
2123             bool exceptionsAvailable = IsFaulted && ExceptionRecorded;
2124             Contract.Assert(exceptionsAvailable, "Must only be used when the task has faulted with exceptions.");
2125             return exceptionsAvailable ?
2126                 m_contingentProperties.m_exceptionsHolder.GetExceptionDispatchInfos() :
2127                 new ReadOnlyCollection<ExceptionDispatchInfo>(new ExceptionDispatchInfo[0]);
2128         }
2129
2130         /// <summary>Gets the ExceptionDispatchInfo containing the OperationCanceledException for this task.</summary>
2131         /// <returns>The ExceptionDispatchInfo.  May be null if no OCE was stored for the task.</returns>
2132         internal ExceptionDispatchInfo GetCancellationExceptionDispatchInfo()
2133         {
2134             Contract.Assert(IsCanceled, "Must only be used when the task has canceled.");
2135             var props = m_contingentProperties;
2136             if (props == null) return null;
2137             var holder = props.m_exceptionsHolder;
2138             if (holder == null) return null;
2139             return holder.GetCancellationExceptionDispatchInfo(); // may be null
2140         }
2141
2142         /// <summary>
2143         /// Throws an aggregate exception if the task contains exceptions. 
2144         /// </summary>
2145         internal void ThrowIfExceptional(bool includeTaskCanceledExceptions)
2146         {
2147             Contract.Requires(IsCompleted, "ThrowIfExceptional(): Expected IsCompleted == true");
2148
2149             Exception exception = GetExceptions(includeTaskCanceledExceptions);
2150             if (exception != null)
2151             {
2152                 UpdateExceptionObservedStatus();
2153                 throw exception;
2154             }
2155         }
2156
2157         /// <summary>
2158         /// Checks whether this is an attached task, and whether we are being called by the parent task.
2159         /// And sets the TASK_STATE_EXCEPTIONOBSERVEDBYPARENT status flag based on that.
2160         /// 
2161         /// This is meant to be used internally when throwing an exception, and when WaitAll is gathering 
2162         /// exceptions for tasks it waited on. If this flag gets set, the implicit wait on children 
2163         /// will skip exceptions to prevent duplication.
2164         /// 
2165         /// This should only be called when this task has completed with an exception
2166         /// 
2167         /// </summary>
2168         internal void UpdateExceptionObservedStatus()
2169         {
2170             if ((m_parent != null)
2171                 && ((Options & TaskCreationOptions.AttachedToParent) != 0)
2172                 && ((m_parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0)
2173                 && Task.InternalCurrent == m_parent)
2174             {
2175                 m_stateFlags |= TASK_STATE_EXCEPTIONOBSERVEDBYPARENT;
2176             }
2177         }
2178
2179         /// <summary>
2180         /// Checks whether the TASK_STATE_EXCEPTIONOBSERVEDBYPARENT status flag is set,
2181         /// This will only be used by the implicit wait to prevent double throws
2182         /// 
2183         /// </summary>
2184         internal bool IsExceptionObservedByParent
2185         {
2186             get
2187             {
2188                 return (m_stateFlags & TASK_STATE_EXCEPTIONOBSERVEDBYPARENT) != 0;
2189             }
2190         }
2191
2192         /// <summary>
2193         /// Checks whether the body was ever invoked. Used by task scheduler code to verify custom schedulers actually ran the task.
2194         /// </summary>
2195         internal bool IsDelegateInvoked
2196         {
2197             get
2198             {
2199                 return (m_stateFlags & TASK_STATE_DELEGATE_INVOKED) != 0;
2200             }
2201         }
2202
2203         /// <summary>
2204         /// Signals completion of this particular task.
2205         ///
2206         /// The bUserDelegateExecuted parameter indicates whether this Finish() call comes following the
2207         /// full execution of the user delegate. 
2208         /// 
2209         /// If bUserDelegateExecuted is false, it mean user delegate wasn't invoked at all (either due to
2210         /// a cancellation request, or because this task is a promise style Task). In this case, the steps
2211         /// involving child tasks (i.e. WaitForChildren) will be skipped.
2212         /// 
2213         /// </summary>
2214         internal void Finish(bool bUserDelegateExecuted)
2215         {
2216             if (!bUserDelegateExecuted)
2217             {
2218                 // delegate didn't execute => no children. We can safely call the remaining finish stages
2219                 FinishStageTwo();
2220             }
2221             else
2222             {
2223                 var props = m_contingentProperties;
2224
2225                 if (props == null || // no contingent properties means no children, so it's safe to complete ourselves
2226                     (props.m_completionCountdown == 1 && !IsSelfReplicatingRoot) ||
2227                     // Count of 1 => either all children finished, or there were none. Safe to complete ourselves 
2228                     // without paying the price of an Interlocked.Decrement.
2229                     // However we need to exclude self replicating root tasks from this optimization, because
2230                     // they can have children joining in, or finishing even after the root task delegate is done.
2231                     Interlocked.Decrement(ref props.m_completionCountdown) == 0) // Reaching this sub clause means there may be remaining active children,
2232                 // and we could be racing with one of them to call FinishStageTwo().
2233                 // So whoever does the final Interlocked.Dec is responsible to finish.
2234                 {
2235                     FinishStageTwo();
2236                 }
2237                 else
2238                 {
2239                     // Apparently some children still remain. It will be up to the last one to process the completion of this task on their own thread.
2240                     // We will now yield the thread back to ThreadPool. Mark our state appropriately before getting out.
2241
2242                     // We have to use an atomic update for this and make sure not to overwrite a final state, 
2243                     // because at this very moment the last child's thread may be concurrently completing us.
2244                     // Otherwise we risk overwriting the TASK_STATE_RAN_TO_COMPLETION, _CANCELED or _FAULTED bit which may have been set by that child task.
2245                     // Note that the concurrent update by the last child happening in FinishStageTwo could still wipe out the TASK_STATE_WAITING_ON_CHILDREN flag, 
2246                     // but it is not critical to maintain, therefore we dont' need to intruduce a full atomic update into FinishStageTwo
2247
2248                     AtomicStateUpdate(TASK_STATE_WAITING_ON_CHILDREN, TASK_STATE_FAULTED | TASK_STATE_CANCELED | TASK_STATE_RAN_TO_COMPLETION);
2249                 }
2250
2251                 // 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.
2252                 // we use a local variable for exceptional children here because some other thread may be nulling out m_contingentProperties.m_exceptionalChildren 
2253                 List<Task> exceptionalChildren = props != null ? props.m_exceptionalChildren : null;
2254
2255                 if (exceptionalChildren != null)
2256                 {
2257                     lock (exceptionalChildren)
2258                     {
2259                         exceptionalChildren.RemoveAll(s_IsExceptionObservedByParentPredicate); // RemoveAll has better performance than doing it ourselves
2260                     }
2261                 }
2262             }
2263         }
2264
2265         // statically allocated delegate for the removeall expression in Finish()
2266         private readonly static Predicate<Task> s_IsExceptionObservedByParentPredicate = new Predicate<Task>((t) => { return t.IsExceptionObservedByParent; });
2267
2268         /// <summary>
2269         /// FinishStageTwo is to be executed as soon as we known there are no more children to complete. 
2270         /// 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)
2271         ///              ii) or on the thread that executed the last child.
2272         /// </summary>
2273         internal void FinishStageTwo()
2274         {
2275             AddExceptionsFromChildren();
2276
2277             // At this point, the task is done executing and waiting for its children,
2278             // we can transition our task to a completion state.  
2279             int completionState;
2280             if (ExceptionRecorded)
2281             {
2282                 completionState = TASK_STATE_FAULTED;
2283                 if (AsyncCausalityTracer.LoggingOn)
2284                     AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Error);
2285
2286                 if (Task.s_asyncDebuggingEnabled)
2287                 {
2288                     RemoveFromActiveTasks(this.Id);
2289                 }
2290             }
2291             else if (IsCancellationRequested && IsCancellationAcknowledged)
2292             {
2293                 // We transition into the TASK_STATE_CANCELED final state if the task's CT was signalled for cancellation, 
2294                 // and the user delegate acknowledged the cancellation request by throwing an OCE, 
2295                 // and the task hasn't otherwise transitioned into faulted state. (TASK_STATE_FAULTED trumps TASK_STATE_CANCELED)
2296                 //
2297                 // If the task threw an OCE without cancellation being requestsed (while the CT not being in signaled state),
2298                 // then we regard it as a regular exception
2299
2300                 completionState = TASK_STATE_CANCELED;
2301                 if (AsyncCausalityTracer.LoggingOn)
2302                     AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Canceled);
2303
2304                 if (Task.s_asyncDebuggingEnabled)
2305                 {
2306                     RemoveFromActiveTasks(this.Id);
2307                 }
2308             }
2309             else
2310             {
2311                 completionState = TASK_STATE_RAN_TO_COMPLETION;
2312                 if (AsyncCausalityTracer.LoggingOn)
2313                     AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
2314
2315                 if (Task.s_asyncDebuggingEnabled)
2316                 {
2317                     RemoveFromActiveTasks(this.Id);
2318                 }
2319             }
2320
2321             // Use Interlocked.Exchange() to effect a memory fence, preventing
2322             // any SetCompleted() (or later) instructions from sneak back before it.
2323             Interlocked.Exchange(ref m_stateFlags, m_stateFlags | completionState);
2324
2325             // Set the completion event if it's been lazy allocated.
2326             // And if we made a cancellation registration, it's now unnecessary.
2327             var cp = m_contingentProperties;
2328             if (cp != null)
2329             {
2330                 cp.SetCompleted();
2331                 cp.DeregisterCancellationCallback();
2332             }
2333
2334             // ready to run continuations and notify parent.
2335             FinishStageThree();
2336         }
2337
2338
2339         /// <summary>
2340         /// Final stage of the task completion code path. Notifies the parent (if any) that another of its childre are done, and runs continuations.
2341         /// This function is only separated out from FinishStageTwo because these two operations are also needed to be called from CancellationCleanupLogic()
2342         /// </summary>
2343         internal void FinishStageThree()
2344         {
2345             // Release the action so that holding this task object alive doesn't also
2346             // hold alive the body of the task.  We do this before notifying a parent,
2347             // so that if notifying the parent completes the parent and causes
2348             // its synchronous continuations to run, the GC can collect the state
2349             // in the interim.  And we do it before finishing continuations, because
2350             // continuations hold onto the task, and therefore are keeping it alive.
2351             m_action = null;
2352
2353             // Notify parent if this was an attached task
2354             if (m_parent != null
2355                  && ((m_parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0)
2356                  && (((TaskCreationOptions)(m_stateFlags & OptionsMask)) & TaskCreationOptions.AttachedToParent) != 0)
2357             {
2358                 m_parent.ProcessChildCompletion(this);
2359             }
2360
2361             // Activate continuations (if any).
2362             FinishContinuations();
2363         }
2364
2365         /// <summary>
2366         /// This is called by children of this task when they are completed.
2367         /// </summary>
2368         internal void ProcessChildCompletion(Task childTask)
2369         {
2370             Contract.Requires(childTask != null);
2371             Contract.Requires(childTask.IsCompleted, "ProcessChildCompletion was called for an uncompleted task");
2372
2373             Contract.Assert(childTask.m_parent == this, "ProcessChildCompletion should only be called for a child of this task");
2374
2375             var props = m_contingentProperties;
2376
2377             // if the child threw and we haven't observed it we need to save it for future reference
2378             if (childTask.IsFaulted && !childTask.IsExceptionObservedByParent)
2379             {
2380                 // Lazily initialize the child exception list
2381                 if (props.m_exceptionalChildren == null)
2382                 {
2383                     Interlocked.CompareExchange(ref props.m_exceptionalChildren, new List<Task>(), null);
2384                 }
2385
2386                 // In rare situations involving AppDomainUnload, it's possible (though unlikely) for FinishStageTwo() to be called
2387                 // multiple times for the same task.  In that case, AddExceptionsFromChildren() could be nulling m_exceptionalChildren
2388                 // out at the same time that we're processing it, resulting in a NullReferenceException here.  We'll protect
2389                 // ourselves by caching m_exceptionChildren in a local variable.
2390                 List<Task> tmp = props.m_exceptionalChildren;
2391                 if (tmp != null)
2392                 {
2393                     lock (tmp)
2394                     {
2395                         tmp.Add(childTask);
2396                     }
2397                 }
2398
2399             }
2400
2401             if (Interlocked.Decrement(ref props.m_completionCountdown) == 0)
2402             {
2403                 // This call came from the final child to complete, and apparently we have previously given up this task's right to complete itself.
2404                 // So we need to invoke the final finish stage.
2405
2406                 FinishStageTwo();
2407             }
2408         }
2409
2410         /// <summary>
2411         /// This is to be called just before the task does its final state transition. 
2412         /// It traverses the list of exceptional children, and appends their aggregate exceptions into this one's exception list
2413         /// </summary>
2414         internal void AddExceptionsFromChildren()
2415         {
2416             // In rare occurences during AppDomainUnload() processing, it is possible for this method to be called
2417             // simultaneously on the same task from two different contexts.  This can result in m_exceptionalChildren
2418             // being nulled out while it is being processed, which could lead to a NullReferenceException.  To
2419             // protect ourselves, we'll cache m_exceptionalChildren in a local variable.
2420             var props = m_contingentProperties;
2421             List<Task> tmp = (props != null) ? props.m_exceptionalChildren : null;
2422
2423             if (tmp != null)
2424             {
2425                 // This lock is necessary because even though AddExceptionsFromChildren is last to execute, it may still 
2426                 // be racing with the code segment at the bottom of Finish() that prunes the exceptional child array. 
2427                 lock (tmp)
2428                 {
2429                     foreach (Task task in tmp)
2430                     {
2431                         // Ensure any exceptions thrown by children are added to the parent.
2432                         // In doing this, we are implicitly marking children as being "handled".
2433                         Contract.Assert(task.IsCompleted, "Expected all tasks in list to be completed");
2434                         if (task.IsFaulted && !task.IsExceptionObservedByParent)
2435                         {
2436                             TaskExceptionHolder exceptionHolder = task.m_contingentProperties.m_exceptionsHolder;
2437                             Contract.Assert(exceptionHolder != null);
2438
2439                             // No locking necessary since child task is finished adding exceptions
2440                             // and concurrent CreateExceptionObject() calls do not constitute
2441                             // a concurrency hazard.
2442                             AddException(exceptionHolder.CreateExceptionObject(false, null));
2443                         }
2444                     }
2445                 }
2446
2447                 // Reduce memory pressure by getting rid of the array
2448                 props.m_exceptionalChildren = null;
2449             }
2450         }
2451
2452         /// <summary>
2453         /// Special purpose Finish() entry point to be used when the task delegate throws a ThreadAbortedException
2454         /// This makes a note in the state flags so that we avoid any costly synchronous operations in the finish codepath
2455         /// such as inlined continuations
2456         /// </summary>
2457         /// <param name="bTAEAddedToExceptionHolder">
2458         /// Indicates whether the ThreadAbortException was added to this task's exception holder. 
2459         /// This should always be true except for the case of non-root self replicating task copies.
2460         /// </param>
2461         /// <param name="delegateRan">Whether the delegate was executed.</param>
2462         internal void FinishThreadAbortedTask(bool bTAEAddedToExceptionHolder, bool delegateRan)
2463         {
2464             Contract.Assert(!bTAEAddedToExceptionHolder || (m_contingentProperties != null && m_contingentProperties.m_exceptionsHolder != null),
2465                             "FinishThreadAbortedTask() called on a task whose exception holder wasn't initialized");
2466
2467             // this will only be false for non-root self replicating task copies, because all of their exceptions go to the root task.
2468             if (bTAEAddedToExceptionHolder)
2469                 m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false);
2470
2471             // If this method has already been called for this task, or if this task has already completed, then
2472             // return before actually calling Finish().
2473             if (!AtomicStateUpdate(TASK_STATE_THREAD_WAS_ABORTED,
2474                             TASK_STATE_THREAD_WAS_ABORTED | TASK_STATE_RAN_TO_COMPLETION | TASK_STATE_FAULTED | TASK_STATE_CANCELED))
2475             {
2476                 return;
2477             }
2478
2479             Finish(delegateRan);
2480
2481         }
2482
2483
2484         /// <summary>
2485         /// Executes the task. This method will only be called once, and handles bookeeping associated with
2486         /// self-replicating tasks, in addition to performing necessary exception marshaling.
2487         /// </summary>
2488         private void Execute()
2489         {
2490             if (IsSelfReplicatingRoot)
2491             {
2492                 ExecuteSelfReplicating(this);
2493             }
2494             else
2495             {
2496                 try
2497                 {
2498                     InnerInvoke();
2499                 }
2500                 catch (ThreadAbortException tae)
2501                 {
2502                     // Don't record the TAE or call FinishThreadAbortedTask for a child replica task --
2503                     // it's already been done downstream.
2504                     if (!IsChildReplica)
2505                     {
2506                         // Record this exception in the task's exception list
2507                         HandleException(tae);
2508
2509                         // This is a ThreadAbortException and it will be rethrown from this catch clause, causing us to 
2510                         // skip the regular Finish codepath. In order not to leave the task unfinished, we now call 
2511                         // FinishThreadAbortedTask here.
2512                         FinishThreadAbortedTask(true, true);
2513                     }
2514                 }
2515                 catch (Exception exn)
2516                 {
2517                     // Record this exception in the task's exception list
2518                     HandleException(exn);
2519                 }
2520             }
2521         }
2522
2523         // Allows (internal) deriving classes to support limited replication.
2524         // (By default, replication is basically unlimited).
2525         internal virtual bool ShouldReplicate()
2526         {
2527             return true;
2528         }
2529
2530         // Allows (internal) deriving classes to instantiate the task replica as a Task super class of their choice
2531         // (By default, we create a regular Task instance)
2532         internal virtual Task CreateReplicaTask(Action<object> taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
2533                                             TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica)
2534         {
2535             return new Task(taskReplicaDelegate, stateObject, parentTask, default(CancellationToken),
2536                             creationOptionsForReplica, internalOptionsForReplica, parentTask.ExecutingTaskScheduler);
2537         }
2538
2539         // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
2540         internal virtual Object SavedStateForNextReplica
2541         {
2542             get { return null; }
2543
2544             set { /*do nothing*/ }
2545         }
2546
2547         // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
2548         internal virtual Object SavedStateFromPreviousReplica
2549         {
2550             get { return null; }
2551
2552             set { /*do nothing*/ }
2553         }
2554
2555         // Allows internal deriving classes to support replicas that exit prematurely and want to hand over the child replica that they
2556         // had queued, so that the replacement replica can work with that child task instead of queuing up yet another one
2557         internal virtual Task HandedOverChildReplica
2558         {
2559             get { return null; }
2560
2561             set { /* do nothing*/ }
2562         }
2563
2564         private static void ExecuteSelfReplicating(Task root)
2565         {
2566             TaskCreationOptions creationOptionsForReplicas = root.CreationOptions | TaskCreationOptions.AttachedToParent;
2567             InternalTaskOptions internalOptionsForReplicas =
2568                 InternalTaskOptions.ChildReplica |  // child replica flag disables self replication for the replicas themselves.
2569                 InternalTaskOptions.SelfReplicating |  // we still want to identify this as part of a self replicating group
2570                 InternalTaskOptions.QueuedByRuntime;   // we queue and cancel these tasks internally, so don't allow CT registration to take place
2571
2572
2573             // Important Note: The child replicas we launch from here will be attached the root replica (by virtue of the root.CreateReplicaTask call)
2574             // because we need the root task to receive all their exceptions, and to block until all of them return
2575
2576
2577             // This variable is captured in a closure and shared among all replicas.
2578             bool replicasAreQuitting = false;
2579
2580             // Set up a delegate that will form the body of the root and all recursively created replicas.
2581             Action<object> taskReplicaDelegate = null;
2582             taskReplicaDelegate = delegate
2583             {
2584                 Task currentTask = Task.InternalCurrent;
2585
2586
2587                 // Check if a child task has been handed over by a prematurely quiting replica that we might be a replacement for.
2588                 Task childTask = currentTask.HandedOverChildReplica;
2589
2590                 if (childTask == null)
2591                 {
2592                     // Apparently we are not a replacement task. This means we need to queue up a child task for replication to progress
2593
2594                     // Down-counts a counter in the root task.
2595                     if (!root.ShouldReplicate()) return;
2596
2597                     // If any of the replicas have quit, we will do so ourselves.
2598                     if (Volatile.Read(ref replicasAreQuitting))
2599                     {
2600                         return;
2601                     }
2602
2603                     // Propagate a copy of the context from the root task. It may be null if flow was suppressed.
2604                     ExecutionContext creatorContext = root.CapturedContext;
2605
2606
2607                     childTask = root.CreateReplicaTask(taskReplicaDelegate, root.m_stateObject, root, root.ExecutingTaskScheduler,
2608                                                        creationOptionsForReplicas, internalOptionsForReplicas);
2609
2610                     childTask.CapturedContext = CopyExecutionContext(creatorContext);
2611
2612                     childTask.ScheduleAndStart(false);
2613                 }
2614
2615
2616
2617                 // Finally invoke the meat of the task.
2618                 // Note that we are directly calling root.InnerInvoke() even though we are currently be in the action delegate of a child replica 
2619                 // This is because the actual work was passed down in that delegate, and the action delegate of the child replica simply contains this
2620                 // replication control logic.
2621                 try
2622                 {
2623                     // passing in currentTask only so that the parallel debugger can find it
2624                     root.InnerInvokeWithArg(currentTask);
2625                 }
2626                 catch (Exception exn)
2627                 {
2628                     // Record this exception in the root task's exception list
2629                     root.HandleException(exn);
2630
2631                     if (exn is ThreadAbortException)
2632                     {
2633                         // If this is a ThreadAbortException it will escape this catch clause, causing us to skip the regular Finish codepath
2634                         // In order not to leave the task unfinished, we now call FinishThreadAbortedTask here
2635                         currentTask.FinishThreadAbortedTask(false, true);
2636                     }
2637                 }
2638
2639                 Object savedState = currentTask.SavedStateForNextReplica;
2640
2641                 // check for premature exit
2642                 if (savedState != null)
2643                 {
2644                     // the replica decided to exit early
2645                     // we need to queue up a replacement, attach the saved state, and yield the thread right away
2646
2647                     Task replacementReplica = root.CreateReplicaTask(taskReplicaDelegate, root.m_stateObject, root, root.ExecutingTaskScheduler,
2648                                                                     creationOptionsForReplicas, internalOptionsForReplicas);
2649
2650                     // Propagate a copy of the context from the root task to the replacement task
2651                     ExecutionContext creatorContext = root.CapturedContext;
2652                     replacementReplica.CapturedContext = CopyExecutionContext(creatorContext);
2653
2654                     replacementReplica.HandedOverChildReplica = childTask;
2655                     replacementReplica.SavedStateFromPreviousReplica = savedState;
2656
2657                     replacementReplica.ScheduleAndStart(false);
2658                 }
2659                 else
2660                 {
2661                     // The replica finished normally, which means it can't find more work to grab. 
2662                     // Time to mark replicas quitting
2663
2664                     replicasAreQuitting = true;
2665
2666                     // InternalCancel() could conceivably throw in the underlying scheduler's TryDequeue() method.
2667                     // If it does, then make sure that we record it.
2668                     try
2669                     {
2670                         childTask.InternalCancel(true);
2671                     }
2672                     catch (Exception e)
2673                     {
2674                         // Apparently TryDequeue threw an exception.  Before propagating that exception, InternalCancel should have
2675                         // attempted an atomic state transition and a call to CancellationCleanupLogic() on this task. So we know
2676                         // the task was properly cleaned up if it was possible. 
2677                         //
2678                         // Now all we need to do is to Record the exception in the root task.
2679
2680                         root.HandleException(e);
2681                     }
2682
2683                     // No specific action needed if the child could not be canceled
2684                     // because we attached it to the root task, which should therefore be receiving any exceptions from the child,
2685                     // and root.wait will not return before this child finishes anyway.
2686
2687                 }
2688             };
2689
2690             //
2691             // Now we execute as the root task
2692             //
2693             taskReplicaDelegate(null);
2694         }
2695
2696         /// <summary>
2697         /// IThreadPoolWorkItem override, which is the entry function for this task when the TP scheduler decides to run it.
2698         /// 
2699         /// </summary>
2700         [SecurityCritical]
2701         void IThreadPoolWorkItem.ExecuteWorkItem()
2702         {
2703             ExecuteEntry(false);
2704         }
2705
2706         /// <summary>
2707         /// The ThreadPool calls this if a ThreadAbortException is thrown while trying to execute this workitem.  This may occur
2708         /// before Task would otherwise be able to observe it.  
2709         /// </summary>
2710         [SecurityCritical]
2711         void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae)
2712         {
2713             // If the task has marked itself as Completed, then it either a) already observed this exception (so we shouldn't handle it here)
2714             // or b) completed before the exception ocurred (in which case it shouldn't count against this Task).
2715             if (!IsCompleted)
2716             {
2717                 HandleException(tae);
2718                 FinishThreadAbortedTask(true, false);
2719             }
2720         }
2721
2722         /// <summary>
2723         /// Outermost entry function to execute this task. Handles all aspects of executing a task on the caller thread.
2724         /// Currently this is called by IThreadPoolWorkItem.ExecuteWorkItem(), and TaskManager.TryExecuteInline. 
2725         /// 
2726         /// </summary>
2727         /// <param name="bPreventDoubleExecution"> Performs atomic updates to prevent double execution. Should only be set to true
2728         /// in codepaths servicing user provided TaskSchedulers. The ConcRT or ThreadPool schedulers don't need this. </param>
2729         [SecuritySafeCritical]
2730         internal bool ExecuteEntry(bool bPreventDoubleExecution)
2731         {
2732             if (bPreventDoubleExecution || ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0))
2733             {
2734                 int previousState = 0;
2735
2736                 // Do atomic state transition from queued to invoked. If we observe a task that's already invoked,
2737                 // we will return false so that TaskScheduler.ExecuteTask can throw an exception back to the custom scheduler.
2738                 // However we don't want this exception to be throw if the task was already canceled, because it's a
2739                 // legitimate scenario for custom schedulers to dequeue a task and mark it as canceled (example: throttling scheduler)
2740                 if (!AtomicStateUpdate(TASK_STATE_DELEGATE_INVOKED,
2741                                        TASK_STATE_DELEGATE_INVOKED | TASK_STATE_COMPLETED_MASK,
2742                                        ref previousState) && (previousState & TASK_STATE_CANCELED) == 0)
2743                 {
2744                     // This task has already been invoked.  Don't invoke it again.
2745                     return false;
2746                 }
2747             }
2748             else
2749             {
2750                 // Remember that we started running the task delegate.
2751                 m_stateFlags |= TASK_STATE_DELEGATE_INVOKED;
2752             }
2753
2754             if (!IsCancellationRequested && !IsCanceled)
2755             {
2756                 ExecuteWithThreadLocal(ref t_currentTask);
2757             }
2758             else if (!IsCanceled)
2759             {
2760                 int prevState = Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_CANCELED);
2761                 if ((prevState & TASK_STATE_CANCELED) == 0)
2762                 {
2763                     CancellationCleanupLogic();
2764                 }
2765             }
2766
2767             return true;
2768         }
2769
2770         // A trick so we can refer to the TLS slot with a byref.
2771         [SecurityCritical]
2772         private void ExecuteWithThreadLocal(ref Task currentTaskSlot)
2773         {
2774             // Remember the current task so we can restore it after running, and then
2775             Task previousTask = currentTaskSlot;
2776
2777             // ETW event for Task Started
2778             var etwLog = TplEtwProvider.Log;
2779             Guid savedActivityID = new Guid();
2780             bool etwIsEnabled = etwLog.IsEnabled();
2781             if (etwIsEnabled)
2782             {
2783                 if (etwLog.TasksSetActivityIds)
2784                     EventSource.SetCurrentThreadActivityId(TplEtwProvider.CreateGuidForTaskID(this.Id), out savedActivityID);
2785                 // previousTask holds the actual "current task" we want to report in the event
2786                 if (previousTask != null)
2787                     etwLog.TaskStarted(previousTask.m_taskScheduler.Id, previousTask.Id, this.Id);
2788                 else
2789                     etwLog.TaskStarted(TaskScheduler.Current.Id, 0, this.Id);
2790             }
2791
2792             if (AsyncCausalityTracer.LoggingOn)
2793                 AsyncCausalityTracer.TraceSynchronousWorkStart(CausalityTraceLevel.Required, this.Id, CausalitySynchronousWork.Execution);
2794
2795
2796             try
2797             {
2798                 // place the current task into TLS.
2799                 currentTaskSlot = this;
2800
2801                 ExecutionContext ec = CapturedContext;
2802                 if (ec == null)
2803                 {
2804                     // No context, just run the task directly.
2805                     Execute();
2806                 }
2807                 else
2808                 {
2809                     if (IsSelfReplicatingRoot || IsChildReplica)
2810                     {
2811                         CapturedContext = CopyExecutionContext(ec);
2812                     }
2813
2814                     // Run the task.  We need a simple shim that converts the
2815                     // object back into a Task object, so that we can Execute it.
2816
2817                     // Lazily initialize the callback delegate; benign ----
2818                     var callback = s_ecCallback;
2819                     if (callback == null) s_ecCallback = callback = new ContextCallback(ExecutionContextCallback);
2820 #if PFX_LEGACY_3_5
2821                     ExecutionContext.Run(ec, callback, this);
2822 #else
2823                     ExecutionContext.Run(ec, callback, this, true);
2824 #endif
2825                 }
2826
2827                 if (AsyncCausalityTracer.LoggingOn)
2828                     AsyncCausalityTracer.TraceSynchronousWorkCompletion(CausalityTraceLevel.Required, CausalitySynchronousWork.Execution);
2829
2830                 Finish(true);
2831             }
2832             finally
2833             {
2834                 currentTaskSlot = previousTask;
2835                 
2836                 // ETW event for Task Completed
2837                 if (etwIsEnabled)
2838                 {
2839                     // previousTask holds the actual "current task" we want to report in the event
2840                     if (previousTask != null)
2841                         etwLog.TaskCompleted(previousTask.m_taskScheduler.Id, previousTask.Id, this.Id, IsFaulted);
2842                     else
2843                         etwLog.TaskCompleted(TaskScheduler.Current.Id, 0, this.Id, IsFaulted);
2844
2845                     if (etwLog.TasksSetActivityIds)
2846                         EventSource.SetCurrentThreadActivityId(savedActivityID);
2847                 }
2848             }
2849         }
2850
2851         // Cached callback delegate that's lazily initialized due to ContextCallback being SecurityCritical
2852         [SecurityCritical]
2853         private static ContextCallback s_ecCallback;
2854
2855         [SecurityCritical]
2856         private static void ExecutionContextCallback(object obj)
2857         {
2858             Task task = obj as Task;
2859             Contract.Assert(task != null, "expected a task object");
2860             task.Execute();
2861         }
2862
2863
2864         /// <summary>
2865         /// The actual code which invokes the body of the task. This can be overriden in derived types.
2866         /// </summary>
2867         internal virtual void InnerInvoke()
2868         {
2869             // Invoke the delegate
2870             Contract.Assert(m_action != null, "Null action in InnerInvoke()");
2871             var action = m_action as Action;
2872             if (action != null)
2873             {
2874                 action();
2875                 return;
2876             }
2877             var actionWithState = m_action as Action<object>;
2878             if (actionWithState != null)
2879             {
2880                 actionWithState(m_stateObject);
2881                 return;
2882             }
2883             Contract.Assert(false, "Invalid m_action in Task");
2884         }
2885
2886         /// <summary>
2887         /// Alternate InnerInvoke prototype to be called from ExecuteSelfReplicating() so that
2888         /// the Parallel Debugger can discover the actual task being invoked. 
2889         /// Details: Here, InnerInvoke is actually being called on the rootTask object while we are actually executing the
2890         /// childTask. And the debugger needs to discover the childTask, so we pass that down as an argument.
2891         /// The NoOptimization and NoInlining flags ensure that the childTask pointer is retained, and that this
2892         /// function appears on the callstack.
2893         /// </summary>
2894         /// <param name="childTask"></param>
2895         [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
2896         internal void InnerInvokeWithArg(Task childTask)
2897         {
2898             InnerInvoke();
2899         }
2900
2901         /// <summary>
2902         /// Performs whatever handling is necessary for an unhandled exception. Normally
2903         /// this just entails adding the exception to the holder object. 
2904         /// </summary>
2905         /// <param name="unhandledException">The exception that went unhandled.</param>
2906         private void HandleException(Exception unhandledException)
2907         {
2908             Contract.Requires(unhandledException != null);
2909
2910             OperationCanceledException exceptionAsOce = unhandledException as OperationCanceledException;
2911             if (exceptionAsOce != null && IsCancellationRequested &&
2912                 m_contingentProperties.m_cancellationToken == exceptionAsOce.CancellationToken)
2913             {
2914                 // All conditions are satisfied for us to go into canceled state in Finish().
2915                 // Mark the acknowledgement.  The exception is also stored to enable it to be
2916                 // the exception propagated from an await.
2917
2918                 SetCancellationAcknowledged();
2919                 AddException(exceptionAsOce, representsCancellation: true);
2920             }
2921             else
2922             {
2923                 // Other exceptions, including any OCE from the task that doesn't match the tasks' own CT, 
2924                 // or that gets thrown without the CT being set will be treated as an ordinary exception 
2925                 // and added to the aggregate.
2926
2927                 AddException(unhandledException);
2928             }
2929         }
2930
2931         #region Await Support
2932         /// <summary>Gets an awaiter used to await this <see cref="System.Threading.Tasks.Task"/>.</summary>
2933         /// <returns>An awaiter instance.</returns>
2934         /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
2935         public TaskAwaiter GetAwaiter()
2936         {
2937             return new TaskAwaiter(this);
2938         }
2939
2940         /// <summary>Configures an awaiter used to await this <see cref="System.Threading.Tasks.Task"/>.</summary>
2941         /// <param name="continueOnCapturedContext">
2942         /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
2943         /// </param>
2944         /// <returns>An object used to await this task.</returns>
2945         public ConfiguredTaskAwaitable ConfigureAwait(bool continueOnCapturedContext)
2946         {
2947             return new ConfiguredTaskAwaitable(this, continueOnCapturedContext);
2948         }
2949
2950         /// <summary>
2951         /// Sets a continuation onto the <see cref="System.Threading.Tasks.Task"/>.
2952         /// The continuation is scheduled to run in the current synchronization context is one exists, 
2953         /// otherwise in the current task scheduler.
2954         /// </summary>
2955         /// <param name="continuationAction">The action to invoke when the <see cref="System.Threading.Tasks.Task"/> has completed.</param>
2956         /// <param name="continueOnCapturedContext">
2957         /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
2958         /// </param>
2959         /// <param name="flowExecutionContext">Whether to flow ExecutionContext across the await.</param>
2960         /// <param name="stackMark">A stack crawl mark tied to execution context.</param>
2961         /// <exception cref="System.InvalidOperationException">The awaiter was not properly initialized.</exception>
2962         [SecurityCritical]
2963         internal void SetContinuationForAwait(
2964             Action continuationAction, bool continueOnCapturedContext, bool flowExecutionContext, ref StackCrawlMark stackMark)
2965         {
2966             Contract.Requires(continuationAction != null);
2967
2968             // Create the best AwaitTaskContinuation object given the request.
2969             // If this remains null by the end of the function, we can use the 
2970             // continuationAction directly without wrapping it.
2971             TaskContinuation tc = null;
2972
2973             // If the user wants the continuation to run on the current "context" if there is one...
2974             if (continueOnCapturedContext)
2975             {
2976                 // First try getting the current synchronization context.
2977                 // If the current context is really just the base SynchronizationContext type, 
2978                 // which is intended to be equivalent to not having a current SynchronizationContext at all, 
2979                 // then ignore it.  This helps with performance by avoiding unnecessary posts and queueing
2980                 // of work items, but more so it ensures that if code happens to publish the default context 
2981                 // as current, it won't prevent usage of a current task scheduler if there is one.
2982                 var syncCtx = SynchronizationContext.CurrentNoFlow;
2983                 if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
2984                 {
2985                     tc = new SynchronizationContextAwaitTaskContinuation(syncCtx, continuationAction, flowExecutionContext, ref stackMark);
2986                 }
2987                 else
2988                 {
2989                     // If there was no SynchronizationContext, then try for the current scheduler.
2990                     // We only care about it if it's not the default.
2991                     var scheduler = TaskScheduler.InternalCurrent;
2992                     if (scheduler != null && scheduler != TaskScheduler.Default)
2993                     {
2994                         tc = new TaskSchedulerAwaitTaskContinuation(scheduler, continuationAction, flowExecutionContext, ref stackMark);
2995                     }
2996                 }
2997             }
2998
2999             if (tc == null && flowExecutionContext)
3000             {
3001                 // We're targeting the default scheduler, so we can use the faster path
3002                 // that assumes the default, and thus we don't need to store it.  If we're flowing
3003                 // ExecutionContext, we need to capture it and wrap it in an AwaitTaskContinuation.
3004                 // Otherwise, we're targeting the default scheduler and we don't need to flow ExecutionContext, so
3005                 // we don't actually need a continuation object.  We can just store/queue the action itself.
3006                 tc = new AwaitTaskContinuation(continuationAction, flowExecutionContext: true, stackMark: ref stackMark);
3007             }
3008
3009             // Now register the continuation, and if we couldn't register it because the task is already completing,
3010             // process the continuation directly (in which case make sure we schedule the continuation
3011             // rather than inlining it, the latter of which could result in a rare but possible stack overflow).
3012             if (tc != null)
3013             {
3014                 if (!AddTaskContinuation(tc, addBeforeOthers: false))
3015                     tc.Run(this, bCanInlineContinuationTask: false);
3016             }
3017             else
3018             {
3019                 Contract.Assert(!flowExecutionContext, "We already determined we're not required to flow context.");
3020                 if (!AddTaskContinuation(continuationAction, addBeforeOthers: false))
3021                     AwaitTaskContinuation.UnsafeScheduleAction(continuationAction, this);
3022             }
3023         }
3024
3025         /// <summary>Creates an awaitable that asynchronously yields back to the current context when awaited.</summary>
3026         /// <returns>
3027         /// A context that, when awaited, will asynchronously transition back into the current context at the 
3028         /// time of the await. If the current SynchronizationContext is non-null, that is treated as the current context.
3029         /// Otherwise, TaskScheduler.Current is treated as the current context.
3030         /// </returns>
3031         public static YieldAwaitable Yield()
3032         {
3033             return new YieldAwaitable();
3034         }
3035         #endregion
3036
3037         /// <summary>
3038         /// Waits for the <see cref="Task"/> to complete execution.
3039         /// </summary>
3040         /// <exception cref="T:System.AggregateException">
3041         /// The <see cref="Task"/> was canceled -or- an exception was thrown during
3042         /// the execution of the <see cref="Task"/>.
3043         /// </exception>
3044         public void Wait()
3045         {
3046 #if DEBUG
3047             bool waitResult =
3048 #endif
3049             Wait(Timeout.Infinite, default(CancellationToken));
3050
3051 #if DEBUG
3052             Contract.Assert(waitResult, "expected wait to succeed");
3053 #endif
3054         }
3055
3056         /// <summary>
3057         /// Waits for the <see cref="Task"/> to complete execution.
3058         /// </summary>
3059         /// <param name="timeout">
3060         /// A <see cref="System.TimeSpan"/> that represents the number of milliseconds to wait, or a <see
3061         /// cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
3062         /// </param>
3063         /// <returns>
3064         /// true if the <see cref="Task"/> completed execution within the allotted time; otherwise, false.
3065         /// </returns>
3066         /// <exception cref="T:System.AggregateException">
3067         /// The <see cref="Task"/> was canceled -or- an exception was thrown during the execution of the <see
3068         /// cref="Task"/>.
3069         /// </exception>
3070         /// <exception cref="T:System.ArgumentOutOfRangeException">
3071         /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents an
3072         /// infinite time-out -or- timeout is greater than
3073         /// <see cref="System.Int32.MaxValue"/>.
3074         /// </exception>
3075         public bool Wait(TimeSpan timeout)
3076         {
3077             long totalMilliseconds = (long)timeout.TotalMilliseconds;
3078             if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
3079             {
3080                 throw new ArgumentOutOfRangeException("timeout");
3081             }
3082
3083             return Wait((int)totalMilliseconds, default(CancellationToken));
3084         }
3085
3086
3087         /// <summary>
3088         /// Waits for the <see cref="Task"/> to complete execution.
3089         /// </summary>
3090         /// <param name="cancellationToken">
3091         /// A <see cref="CancellationToken"/> to observe while waiting for the task to complete.
3092         /// </param>
3093         /// <exception cref="T:System.OperationCanceledException">
3094         /// The <paramref name="cancellationToken"/> was canceled.
3095         /// </exception>
3096         /// <exception cref="T:System.AggregateException">
3097         /// The <see cref="Task"/> was canceled -or- an exception was thrown during the execution of the <see
3098         /// cref="Task"/>.
3099         /// </exception>
3100         public void Wait(CancellationToken cancellationToken)
3101         {
3102             Wait(Timeout.Infinite, cancellationToken);
3103         }
3104
3105
3106         /// <summary>
3107         /// Waits for the <see cref="Task"/> to complete execution.
3108         /// </summary>
3109         /// <param name="millisecondsTimeout">
3110         /// The number of milliseconds to wait, or <see cref="System.Threading.Timeout.Infinite"/> (-1) to
3111         /// wait indefinitely.</param>
3112         /// <returns>true if the <see cref="Task"/> completed execution within the allotted time; otherwise,
3113         /// false.
3114         /// </returns>
3115         /// <exception cref="T:System.ArgumentOutOfRangeException">
3116         /// <paramref name="millisecondsTimeout"/> is a negative number other than -1, which represents an
3117         /// infinite time-out.
3118         /// </exception>
3119         /// <exception cref="T:System.AggregateException">
3120         /// The <see cref="Task"/> was canceled -or- an exception was thrown during the execution of the <see
3121         /// cref="Task"/>.
3122         /// </exception>
3123         public bool Wait(int millisecondsTimeout)
3124         {
3125             return Wait(millisecondsTimeout, default(CancellationToken));
3126         }
3127
3128
3129         /// <summary>
3130         /// Waits for the <see cref="Task"/> to complete execution.
3131         /// </summary>
3132         /// <param name="millisecondsTimeout">
3133         /// The number of milliseconds to wait, or <see cref="System.Threading.Timeout.Infinite"/> (-1) to
3134         /// wait indefinitely.
3135         /// </param>
3136         /// <param name="cancellationToken">
3137         /// A <see cref="CancellationToken"/> to observe while waiting for the task to complete.
3138         /// </param>
3139         /// <returns>
3140         /// true if the <see cref="Task"/> completed execution within the allotted time; otherwise, false.
3141         /// </returns>
3142         /// <exception cref="T:System.AggregateException">
3143         /// The <see cref="Task"/> was canceled -or- an exception was thrown during the execution of the <see
3144         /// cref="Task"/>.
3145         /// </exception>
3146         /// <exception cref="T:System.ArgumentOutOfRangeException">
3147         /// <paramref name="millisecondsTimeout"/> is a negative number other than -1, which represents an
3148         /// infinite time-out.
3149         /// </exception>
3150         /// <exception cref="T:System.OperationCanceledException">
3151         /// The <paramref name="cancellationToken"/> was canceled.
3152         /// </exception>
3153         public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
3154         {
3155             if (millisecondsTimeout < -1)
3156             {
3157                 throw new ArgumentOutOfRangeException("millisecondsTimeout");
3158             }
3159             Contract.EndContractBlock();
3160
3161             // Return immediately if we know that we've completed "clean" -- no exceptions, no cancellations
3162             // and if no notification to the debugger is required
3163             if (!IsWaitNotificationEnabledOrNotRanToCompletion) // (!DebuggerBitSet && RanToCompletion)
3164                 return true;
3165
3166             // Wait, and then return if we're still not done.
3167             if (!InternalWait(millisecondsTimeout, cancellationToken))
3168                 return false;
3169
3170             if (IsWaitNotificationEnabledOrNotRanToCompletion) // avoid a few unnecessary volatile reads if we completed successfully
3171             {
3172                 // Notify the debugger of the wait completion if it's requested such a notification
3173                 NotifyDebuggerOfWaitCompletionIfNecessary();
3174
3175                 // If cancellation was requested and the task was canceled, throw an 
3176                 // OperationCanceledException.  This is prioritized ahead of the ThrowIfExceptional
3177                 // call to bring more determinism to cases where the same token is used to 
3178                 // cancel the Wait and to cancel the Task.  Otherwise, there's a ---- between
3179                 // whether the Wait or the Task observes the cancellation request first,
3180                 // and different exceptions result from the different cases.
3181                 if (IsCanceled) cancellationToken.ThrowIfCancellationRequested();
3182
3183                 // If an exception occurred, or the task was cancelled, throw an exception.
3184                 ThrowIfExceptional(true);
3185             }
3186
3187             Contract.Assert((m_stateFlags & TASK_STATE_FAULTED) == 0, "Task.Wait() completing when in Faulted state.");
3188
3189             return true;
3190         }
3191
3192         // Convenience method that wraps any scheduler exception in a TaskSchedulerException
3193         // and rethrows it.
3194         private bool WrappedTryRunInline()
3195         {
3196             if (m_taskScheduler == null)
3197                 return false;
3198
3199             try
3200             {
3201                 return m_taskScheduler.TryRunInline(this, true);
3202             }
3203             catch (Exception e)
3204             {
3205                 // we 1) either received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown
3206                 //    2) or a a ThreadAbortException, which we need to skip here, because it would already have been handled in Task.Execute
3207                 if (!(e is ThreadAbortException))
3208                 {
3209                     TaskSchedulerException tse = new TaskSchedulerException(e);
3210                     throw tse;
3211                 }
3212                 else
3213                 {
3214                     throw;
3215                 }
3216             }
3217         }
3218
3219         /// <summary>
3220         /// The core wait function, which is only accesible internally. It's meant to be used in places in TPL code where 
3221         /// the current context is known or cached.
3222         /// </summary>
3223         [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
3224         internal bool InternalWait(int millisecondsTimeout, CancellationToken cancellationToken)
3225         {
3226             // ETW event for Task Wait Begin
3227             var etwLog = TplEtwProvider.Log;
3228             bool etwIsEnabled = etwLog.IsEnabled();
3229             if (etwIsEnabled)
3230             {
3231                 Task currentTask = Task.InternalCurrent;
3232                 etwLog.TaskWaitBegin(
3233                     (currentTask != null ? currentTask.m_taskScheduler.Id : TaskScheduler.Default.Id), (currentTask != null ? currentTask.Id : 0),
3234                     this.Id, TplEtwProvider.TaskWaitBehavior.Synchronous, 0, System.Threading.Thread.GetDomainID());
3235             }
3236
3237             bool returnValue = IsCompleted;
3238
3239             // If the event hasn't already been set, we will wait.
3240             if (!returnValue)
3241             {
3242                 // Alert a listening debugger that we can't make forward progress unless it slips threads.
3243                 // We call NOCTD for two reasons:
3244                 //    1. If the task runs on another thread, then we'll be blocked here indefinitely.
3245                 //    2. If the task runs inline but takes some time to complete, it will suffer ThreadAbort with possible state corruption,
3246                 //       and it is best to prevent this unless the user explicitly asks to view the value with thread-slipping enabled.
3247                 Debugger.NotifyOfCrossThreadDependency();
3248
3249                 // We will attempt inline execution only if an infinite wait was requested
3250                 // Inline execution doesn't make sense for finite timeouts and if a cancellation token was specified
3251                 // because we don't know how long the task delegate will take.
3252                 if (millisecondsTimeout == Timeout.Infinite && !cancellationToken.CanBeCanceled &&
3253                     WrappedTryRunInline() && IsCompleted) // TryRunInline doesn't guarantee completion, as there may be unfinished children.
3254                 {
3255                     returnValue = true;
3256                 }
3257                 else
3258                 {
3259                     returnValue = SpinThenBlockingWait(millisecondsTimeout, cancellationToken);
3260                 }
3261             }
3262
3263             Contract.Assert(IsCompleted || millisecondsTimeout != Timeout.Infinite);
3264
3265             // ETW event for Task Wait End
3266             if (etwIsEnabled)
3267             {
3268                 Task currentTask = Task.InternalCurrent;
3269                 if (currentTask != null)
3270                 {
3271                     etwLog.TaskWaitEnd(currentTask.m_taskScheduler.Id, currentTask.Id, this.Id);
3272                 }
3273                 else
3274                 {
3275                     etwLog.TaskWaitEnd(TaskScheduler.Default.Id, 0, this.Id);
3276                 }
3277                 // logically the continuation is empty so we immediately fire
3278                 etwLog.TaskWaitContinuationComplete(this.Id);
3279             }
3280
3281             return returnValue;
3282         }
3283
3284         // An MRES that gets set when Invoke is called.  This replaces old logic that looked like this:
3285         //      ManualResetEventSlim mres = new ManualResetEventSlim(false, 0);
3286         //      Action<Task> completionAction = delegate {mres.Set();}
3287         //      AddCompletionAction(completionAction);
3288         // with this:
3289         //      SetOnInvokeMres mres = new SetOnInvokeMres();
3290         //      AddCompletionAction(mres, addBeforeOthers: true);
3291         // which saves a couple of allocations.
3292         //
3293         // Used in SpinThenBlockingWait (below), but could be seen as a general purpose mechanism.
3294         private sealed class SetOnInvokeMres : ManualResetEventSlim, ITaskCompletionAction
3295         {
3296             internal SetOnInvokeMres() : base(false, 0) { }
3297             public void Invoke(Task completingTask) { Set(); }
3298         }
3299
3300         /// <summary>
3301         /// Waits for the task to complete, for a timeout to occur, or for cancellation to be requested.
3302         /// The method first spins and then falls back to blocking on a new event.
3303         /// </summary>
3304         /// <param name="millisecondsTimeout">The timeout.</param>
3305         /// <param name="cancellationToken">The token.</param>
3306         /// <returns>true if the task is completed; otherwise, false.</returns>
3307         private bool SpinThenBlockingWait(int millisecondsTimeout, CancellationToken cancellationToken)
3308         {
3309             bool infiniteWait = millisecondsTimeout == Timeout.Infinite;
3310             uint startTimeTicks = infiniteWait ? 0 : (uint)Environment.TickCount;
3311             bool returnValue = SpinWait(millisecondsTimeout);
3312             if (!returnValue)
3313             {
3314                 var mres = new SetOnInvokeMres();
3315                 try
3316                 {
3317                     AddCompletionAction(mres, addBeforeOthers: true);
3318                     if (infiniteWait)
3319                     {
3320                         returnValue = mres.Wait(Timeout.Infinite, cancellationToken);
3321                     }
3322                     else
3323                     {
3324                         uint elapsedTimeTicks = ((uint)Environment.TickCount) - startTimeTicks;
3325                         if (elapsedTimeTicks < millisecondsTimeout)
3326                         {
3327                             returnValue = mres.Wait((int)(millisecondsTimeout - elapsedTimeTicks), cancellationToken);
3328                         }
3329                     }
3330                 }
3331                 finally
3332                 {
3333                     if (!IsCompleted) RemoveContinuation(mres);
3334                     // Don't Dispose of the MRES, because the continuation off of this task may
3335                     // still be running.  This is ok, however, as we never access the MRES' WaitHandle,
3336                     // and thus no finalizable resources are actually allocated.
3337                 }
3338             }
3339             return returnValue;
3340         }
3341
3342         /// <summary>
3343         /// Spins briefly while checking IsCompleted
3344         /// </summary>
3345         /// <param name="millisecondsTimeout">The timeout.</param>
3346         /// <returns>true if the task is completed; otherwise, false.</returns>
3347         /// <exception cref="System.OperationCanceledException">The wait was canceled.</exception>
3348         private bool SpinWait(int millisecondsTimeout)
3349         {
3350             if (IsCompleted) return true;
3351
3352             if (millisecondsTimeout == 0)
3353             {
3354                 // For 0-timeouts, we just return immediately.
3355                 return false;
3356             }
3357
3358             //This code is pretty similar to the custom spinning in MRES except there is no yieling after we exceed the spin count
3359             int spinCount = PlatformHelper.IsSingleProcessor ? 1 : System.Threading.SpinWait.YIELD_THRESHOLD; //spin only once if we are running on a single CPU
3360             for (int i = 0; i < spinCount; i++)
3361             {
3362                 if (IsCompleted)
3363                 {
3364                     return true;
3365                 }
3366
3367                 if (i == spinCount / 2)
3368                 {
3369                     Thread.Yield();
3370                 }
3371                 else
3372                 {
3373                     Thread.SpinWait(PlatformHelper.ProcessorCount * (4 << i));
3374                 }
3375
3376             }
3377
3378             return IsCompleted;
3379         }
3380
3381         /// <summary>
3382         /// Cancels the <see cref="Task"/>.
3383         /// </summary>
3384         /// <param name="bCancelNonExecutingOnly"> 
3385         /// Indicates whether we should only cancel non-invoked tasks.
3386         /// For the default scheduler this option will only be serviced through TryDequeue.
3387         /// For custom schedulers we also attempt an atomic state transition.
3388         /// </param>
3389         /// <returns>true if the task was successfully canceled; otherwise, false.</returns>
3390         [SecuritySafeCritical]
3391         internal bool InternalCancel(bool bCancelNonExecutingOnly)
3392         {
3393             Contract.Requires((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) == 0, "Task.InternalCancel() did not expect promise-style task");
3394
3395             bool bPopSucceeded = false;
3396             bool mustCleanup = false;
3397
3398             TaskSchedulerException tse = null;
3399
3400             // If started, and running in a task context, we can try to pop the chore.
3401             if ((m_stateFlags & TASK_STATE_STARTED) != 0)
3402             {
3403                 TaskScheduler ts = m_taskScheduler;
3404
3405                 try
3406                 {
3407                     bPopSucceeded = (ts != null) && ts.TryDequeue(this);
3408                 }
3409                 catch (Exception e)
3410                 {
3411                     // TryDequeue threw. We don't know whether the task was properly dequeued or not. So we must let the rest of 
3412                     // the cancellation logic run its course (record the request, attempt atomic state transition and do cleanup where appropriate)
3413                     // Here we will only record a TaskSchedulerException, which will later be thrown at function exit.
3414
3415                     if (!(e is ThreadAbortException))
3416                     {
3417                         tse = new TaskSchedulerException(e);
3418                     }
3419                 }
3420
3421                 bool bRequiresAtomicStartTransition = (ts != null && ts.RequiresAtomicStartTransition) || ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0);
3422
3423                 if (!bPopSucceeded && bCancelNonExecutingOnly && bRequiresAtomicStartTransition)
3424                 {
3425                     // The caller requested cancellation of non-invoked tasks only, and TryDequeue was one way of doing it...
3426                     // Since that seems to have failed, we should now try an atomic state transition (from non-invoked state to canceled)
3427                     // An atomic transition here is only safe if we know we're on a custom task scheduler, which also forces a CAS on ExecuteEntry
3428
3429                     // Even though this task can't have any children, we should be ready for handling any continuations that 
3430                     // may be attached to it (although currently 
3431                     // So we need to remeber whether we actually did the flip, so we can do clean up (finish continuations etc)
3432                     mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED, TASK_STATE_DELEGATE_INVOKED | TASK_STATE_CANCELED);
3433
3434
3435                     // PS: This is slightly different from the regular cancellation codepath 
3436                     // since we record the cancellation request *after* doing the state transition. 
3437                     // However that shouldn't matter too much because the task was never invoked, thus can't have children
3438                 }
3439
3440             }
3441
3442             if (!bCancelNonExecutingOnly || bPopSucceeded || mustCleanup)
3443             {
3444                 // Record the cancellation request.
3445                 RecordInternalCancellationRequest();
3446
3447                 // Determine whether we need to clean up
3448                 // This will be the case 
3449                 //     1) if we were able to pop, and we win the ---- to update task state to TASK_STATE_CANCELED
3450                 //     2) if the task seems to be yet unstarted, and we win the ---- to transition to
3451                 //        TASK_STATE_CANCELED before anyone else can transition into _STARTED or _CANCELED or 
3452                 //        _RAN_TO_COMPLETION or _FAULTED
3453                 // Note that we do not check for TASK_STATE_COMPLETION_RESERVED.  That only applies to promise-style
3454                 // tasks, and a promise-style task should not enter into this codepath.
3455                 if (bPopSucceeded)
3456                 {
3457                     // hitting this would mean something wrong with the AtomicStateUpdate above
3458                     Contract.Assert(!mustCleanup, "Possibly an invalid state transition call was made in InternalCancel()");
3459
3460                     // Include TASK_STATE_DELEGATE_INVOKED in "illegal" bits to protect against the situation where
3461                     // TS.TryDequeue() returns true but the task is still left on the queue.
3462                     mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED, TASK_STATE_CANCELED | TASK_STATE_DELEGATE_INVOKED);
3463                 }
3464                 else if (!mustCleanup && (m_stateFlags & TASK_STATE_STARTED) == 0)
3465                 {
3466                     mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED,
3467                         TASK_STATE_CANCELED | TASK_STATE_STARTED | TASK_STATE_RAN_TO_COMPLETION |
3468                         TASK_STATE_FAULTED | TASK_STATE_DELEGATE_INVOKED);
3469                 }
3470
3471                 // do the cleanup (i.e. set completion event and finish continuations)
3472                 if (mustCleanup)
3473                 {
3474                     CancellationCleanupLogic();
3475                 }
3476             }
3477
3478             if (tse != null)
3479                 throw tse;
3480             else
3481                 return (mustCleanup);
3482         }
3483
3484         // Breaks out logic for recording a cancellation request
3485         internal void RecordInternalCancellationRequest()
3486         {
3487             // Record the cancellation request.
3488             var props = EnsureContingentPropertiesInitialized(needsProtection: true);
3489             props.m_internalCancellationRequested = CANCELLATION_REQUESTED;
3490
3491         }
3492
3493         // Breaks out logic for recording a cancellation request
3494         // This overload should only be used for promise tasks where no cancellation token
3495         // was supplied when the task was created.
3496         internal void RecordInternalCancellationRequest(CancellationToken tokenToRecord)
3497         {
3498             RecordInternalCancellationRequest();
3499
3500             Contract.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0, "Task.RecordInternalCancellationRequest(CancellationToken) only valid for promise-style task");
3501             Contract.Assert(m_contingentProperties.m_cancellationToken == default(CancellationToken));
3502
3503             // Store the supplied cancellation token as this task's token.
3504             // Waiting on this task will then result in an OperationCanceledException containing this token.
3505             if (tokenToRecord != default(CancellationToken))
3506             {
3507                 m_contingentProperties.m_cancellationToken = tokenToRecord;
3508             }
3509         }
3510
3511         // Breaks out logic for recording a cancellation request
3512         // This overload should only be used for promise tasks where no cancellation token
3513         // was supplied when the task was created.
3514         internal void RecordInternalCancellationRequest(CancellationToken tokenToRecord, object cancellationException)
3515         {
3516             RecordInternalCancellationRequest(tokenToRecord);
3517
3518             // Store the supplied cancellation exception
3519             if (cancellationException != null)
3520             {
3521 #if DEBUG
3522                 var oce = cancellationException as OperationCanceledException;
3523                 if (oce == null)
3524                 {
3525                     var edi = cancellationException as ExceptionDispatchInfo;
3526                     Contract.Assert(edi != null, "Expected either an OCE or an EDI");
3527                     oce = edi.SourceException as OperationCanceledException;
3528                     Contract.Assert(oce != null, "Expected EDI to contain an OCE");
3529                 }
3530                 Contract.Assert(oce.CancellationToken == tokenToRecord, 
3531                                 "Expected OCE's token to match the provided token.");
3532 #endif
3533                 AddException(cancellationException, representsCancellation: true);
3534             }
3535         }
3536
3537         // ASSUMES THAT A SUCCESSFUL CANCELLATION HAS JUST OCCURRED ON THIS TASK!!!
3538         // And this method should be called at most once per task.
3539         internal void CancellationCleanupLogic()
3540         {
3541             Contract.Assert((m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_COMPLETION_RESERVED)) != 0, "Task.CancellationCleanupLogic(): Task not canceled or reserved.");
3542             // I'd like to do this, but there is a small window for a race condition.  If someone calls Wait() between InternalCancel() and
3543             // here, that will set m_completionEvent, leading to a meaningless/harmless assertion.
3544             //Contract.Assert((m_completionEvent == null) || !m_completionEvent.IsSet, "Task.CancellationCleanupLogic(): Completion event already set.");
3545
3546             // This may have been set already, but we need to make sure.
3547             Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_CANCELED);
3548
3549             // Fire completion event if it has been lazily initialized
3550             var cp = m_contingentProperties;
3551             if (cp != null)
3552             {
3553                 cp.SetCompleted();
3554                 cp.DeregisterCancellationCallback();
3555             }
3556
3557             if (AsyncCausalityTracer.LoggingOn)
3558                 AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Canceled);
3559
3560             if (Task.s_asyncDebuggingEnabled)
3561             {
3562                 RemoveFromActiveTasks(this.Id);
3563             }
3564
3565             // Notify parents, fire continuations, other cleanup.
3566             FinishStageThree();
3567         }
3568
3569
3570         /// <summary>
3571         /// Sets the task's cancellation acknowledged flag.
3572         /// </summary>    
3573         private void SetCancellationAcknowledged()
3574         {
3575             Contract.Assert(this == Task.InternalCurrent, "SetCancellationAcknowledged() should only be called while this is still the current task");
3576             Contract.Assert(IsCancellationRequested, "SetCancellationAcknowledged() should not be called if the task's CT wasn't signaled");
3577
3578             m_stateFlags |= TASK_STATE_CANCELLATIONACKNOWLEDGED;
3579         }
3580
3581
3582         //
3583         // Continuation passing functionality (aka ContinueWith)
3584         //
3585
3586
3587
3588
3589         /// <summary>
3590         /// Runs all of the continuations, as appropriate.
3591         /// </summary>
3592         [SecuritySafeCritical] // for AwaitTaskContinuation.RunOrScheduleAction
3593         internal void FinishContinuations()
3594         {
3595             // Atomically store the fact that this task is completing.  From this point on, the adding of continuations will
3596             // result in the continuations being run/launched directly rather than being added to the continuation list.
3597             object continuationObject = Interlocked.Exchange(ref m_continuationObject, s_taskCompletionSentinel);
3598             TplEtwProvider.Log.RunningContinuation(Id, continuationObject);
3599
3600             // If continuationObject == null, then we don't have any continuations to process
3601             if (continuationObject != null)
3602             {
3603
3604                 if (AsyncCausalityTracer.LoggingOn)
3605                     AsyncCausalityTracer.TraceSynchronousWorkStart(CausalityTraceLevel.Required, this.Id, CausalitySynchronousWork.CompletionNotification);
3606
3607                 // Skip synchronous execution of continuations if this task's thread was aborted
3608                 bool bCanInlineContinuations = !(((m_stateFlags & TASK_STATE_THREAD_WAS_ABORTED) != 0) ||
3609                                                   (Thread.CurrentThread.ThreadState == ThreadState.AbortRequested) ||
3610                                                   ((m_stateFlags & (int)TaskCreationOptions.RunContinuationsAsynchronously) != 0));
3611
3612                 // Handle the single-Action case
3613                 Action singleAction = continuationObject as Action;
3614                 if (singleAction != null)
3615                 {
3616                     AwaitTaskContinuation.RunOrScheduleAction(singleAction, bCanInlineContinuations, ref t_currentTask);
3617                     LogFinishCompletionNotification();
3618                     return;
3619                 }
3620
3621                 // Handle the single-ITaskCompletionAction case
3622                 ITaskCompletionAction singleTaskCompletionAction = continuationObject as ITaskCompletionAction;
3623                 if (singleTaskCompletionAction != null)
3624                 {
3625                     singleTaskCompletionAction.Invoke(this);
3626                     LogFinishCompletionNotification();
3627                     return;
3628                 }
3629
3630                 // Handle the single-TaskContinuation case
3631                 TaskContinuation singleTaskContinuation = continuationObject as TaskContinuation;
3632                 if (singleTaskContinuation != null)
3633                 {
3634                     singleTaskContinuation.Run(this, bCanInlineContinuations);
3635                     LogFinishCompletionNotification();
3636                     return;
3637                 }
3638
3639                 // Not a single; attempt to cast as list
3640                 List<object> continuations = continuationObject as List<object>;
3641
3642                 if (continuations == null)
3643                 {
3644                     LogFinishCompletionNotification();
3645                     return;  // Not a single or a list; just return
3646                 }
3647
3648                 //
3649                 // Begin processing of continuation list
3650                 //
3651
3652                 // Wait for any concurrent adds or removes to be retired
3653                 lock (continuations) { }
3654                 int continuationCount = continuations.Count;
3655
3656                 // Fire the asynchronous continuations first ...
3657                 for (int i = 0; i < continuationCount; i++)
3658                 {
3659                     // Synchronous continuation tasks will have the ExecuteSynchronously option,
3660                     // and we're looking for asynchronous tasks...
3661                     var tc = continuations[i] as StandardTaskContinuation;
3662                     if (tc != null && (tc.m_options & TaskContinuationOptions.ExecuteSynchronously) == 0)
3663                     {
3664                         TplEtwProvider.Log.RunningContinuationList(Id, i, tc);
3665                         continuations[i] = null; // so that we can skip this later
3666                         tc.Run(this, bCanInlineContinuations);
3667                     }
3668                 }
3669
3670                 // ... and then fire the synchronous continuations (if there are any).
3671                 // This includes ITaskCompletionAction, AwaitTaskContinuations, and
3672                 // Action delegates, which are all by default implicitly synchronous.
3673                 for (int i = 0; i < continuationCount; i++)
3674                 {
3675                     object currentContinuation = continuations[i];
3676                     if (currentContinuation == null) continue;
3677                     continuations[i] = null; // to enable free'ing up memory earlier
3678                     TplEtwProvider.Log.RunningContinuationList(Id, i, currentContinuation);
3679
3680                     // If the continuation is an Action delegate, it came from an await continuation,
3681                     // and we should use AwaitTaskContinuation to run it.
3682                     Action ad = currentContinuation as Action;
3683                     if (ad != null)
3684                     {
3685                         AwaitTaskContinuation.RunOrScheduleAction(ad, bCanInlineContinuations, ref t_currentTask);
3686                     }
3687                     else
3688                     {
3689                         // If it's a TaskContinuation object of some kind, invoke it.
3690                         TaskContinuation tc = currentContinuation as TaskContinuation;
3691                         if (tc != null)
3692                         {
3693                             // We know that this is a synchronous continuation because the
3694                             // asynchronous ones have been weeded out
3695                             tc.Run(this, bCanInlineContinuations);
3696                         }
3697                         // Otherwise, it must be an ITaskCompletionAction, so invoke it.
3698                         else
3699                         {
3700                             Contract.Assert(currentContinuation is ITaskCompletionAction, "Expected continuation element to be Action, TaskContinuation, or ITaskContinuationAction");
3701                             var action = (ITaskCompletionAction)currentContinuation;
3702                             action.Invoke(this);
3703                         }
3704                     }
3705                 }
3706
3707                 LogFinishCompletionNotification();
3708             }
3709         }
3710
3711         private void LogFinishCompletionNotification()
3712         {
3713             if (AsyncCausalityTracer.LoggingOn)
3714                 AsyncCausalityTracer.TraceSynchronousWorkCompletion(CausalityTraceLevel.Required, CausalitySynchronousWork.CompletionNotification);
3715         }
3716
3717         #region Continuation methods
3718
3719         #region Action<Task> continuation
3720         /// <summary>
3721         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
3722         /// </summary>
3723         /// <param name="continuationAction">
3724         /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
3725         /// passed the completed task as an argument.
3726         /// </param>
3727         /// <returns>A new continuation <see cref="Task"/>.</returns>
3728         /// <remarks>
3729         /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
3730         /// completed, whether it completes due to running to completion successfully, faulting due to an
3731         /// unhandled exception, or exiting out early due to being canceled.
3732         /// </remarks>
3733         /// <exception cref="T:System.ArgumentNullException">
3734         /// The <paramref name="continuationAction"/> argument is null.
3735         /// </exception>
3736         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
3737         public Task ContinueWith(Action<Task> continuationAction)
3738         {
3739             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
3740             return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
3741         }
3742
3743         /// <summary>
3744         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
3745         /// </summary>
3746         /// <param name="continuationAction">
3747         /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
3748         /// passed the completed task as an argument.
3749         /// </param>
3750         /// <param name="cancellationToken"> The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
3751         /// <returns>A new continuation <see cref="Task"/>.</returns>
3752         /// <remarks>
3753         /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
3754         /// completed, whether it completes due to running to completion successfully, faulting due to an
3755         /// unhandled exception, or exiting out early due to being canceled.
3756         /// </remarks>
3757         /// <exception cref="T:System.ArgumentNullException">
3758         /// The <paramref name="continuationAction"/> argument is null.
3759         /// </exception>
3760         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
3761         /// has already been disposed.
3762         /// </exception>
3763         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
3764         public Task ContinueWith(Action<Task> continuationAction, CancellationToken cancellationToken)
3765         {
3766             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
3767             return ContinueWith(continuationAction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
3768         }
3769
3770         /// <summary>
3771         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
3772         /// </summary>
3773         /// <param name="continuationAction">
3774         /// An action to run when the <see cref="Task"/> completes.  When run, the delegate will be
3775         /// passed the completed task as an argument.
3776         /// </param>
3777         /// <param name="scheduler">
3778         /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
3779         /// </param>
3780         /// <returns>A new continuation <see cref="Task"/>.</returns>
3781         /// <remarks>
3782         /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
3783         /// completed, whether it completes due to running to completion successfully, faulting due to an
3784         /// unhandled exception, or exiting out early due to being canceled.
3785         /// </remarks>
3786         /// <exception cref="T:System.ArgumentNullException">
3787         /// The <paramref name="continuationAction"/> argument is null.
3788         /// </exception>
3789         /// <exception cref="T:System.ArgumentNullException">
3790         /// The <paramref name="scheduler"/> argument is null.
3791         /// </exception>
3792         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
3793         public Task ContinueWith(Action<Task> continuationAction, TaskScheduler scheduler)
3794         {
3795             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
3796             return ContinueWith(continuationAction, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
3797         }
3798
3799         /// <summary>
3800         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
3801         /// </summary>
3802         /// <param name="continuationAction">
3803         /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
3804         /// passed the completed task as an argument.
3805         /// </param>
3806         /// <param name="continuationOptions">
3807         /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
3808         /// as <see
3809         /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
3810         /// well as execution options, such as <see
3811         /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
3812         /// </param>
3813         /// <returns>A new continuation <see cref="Task"/>.</returns>
3814         /// <remarks>
3815         /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
3816         /// completed. If the continuation criteria specified through the <paramref
3817         /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled
3818         /// instead of scheduled.
3819         /// </remarks>
3820         /// <exception cref="T:System.ArgumentNullException">
3821         /// The <paramref name="continuationAction"/> argument is null.
3822         /// </exception>
3823         /// <exception cref="T:System.ArgumentOutOfRangeException">
3824         /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
3825         /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
3826         /// </exception>
3827         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
3828         public Task ContinueWith(Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
3829         {
3830             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
3831             return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
3832         }
3833
3834         /// <summary>
3835         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
3836         /// </summary>
3837         /// <param name="continuationAction">
3838         /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
3839         /// passed the completed task as an argument.
3840         /// </param>
3841         /// <param name="continuationOptions">
3842         /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
3843         /// as <see
3844         /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
3845         /// well as execution options, such as <see
3846         /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
3847         /// </param>
3848         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
3849         /// <param name="scheduler">
3850         /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
3851         /// execution.
3852         /// </param>
3853         /// <returns>A new continuation <see cref="Task"/>.</returns>
3854         /// <remarks>
3855         /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
3856         /// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
3857         /// are not met, the continuation task will be canceled instead of scheduled.
3858         /// </remarks>
3859         /// <exception cref="T:System.ArgumentNullException">
3860         /// The <paramref name="continuationAction"/> argument is null.
3861         /// </exception>
3862         /// <exception cref="T:System.ArgumentOutOfRangeException">
3863         /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
3864         /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
3865         /// </exception>
3866         /// <exception cref="T:System.ArgumentNullException">
3867         /// The <paramref name="scheduler"/> argument is null.
3868         /// </exception>
3869         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
3870         /// has already been disposed.
3871         /// </exception>
3872         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
3873         public Task ContinueWith(Action<Task> continuationAction, CancellationToken cancellationToken,
3874                                  TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
3875         {
3876             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
3877             return ContinueWith(continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
3878         }
3879
3880         // Same as the above overload, just with a stack mark parameter.
3881         private Task ContinueWith(Action<Task> continuationAction, TaskScheduler scheduler,
3882             CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
3883         {
3884             // Throw on continuation with null action
3885             if (continuationAction == null)
3886             {
3887                 throw new ArgumentNullException("continuationAction");
3888             }
3889
3890             // Throw on continuation with null TaskScheduler
3891             if (scheduler == null)
3892             {
3893                 throw new ArgumentNullException("scheduler");
3894             }
3895             Contract.EndContractBlock();
3896
3897             TaskCreationOptions creationOptions;
3898             InternalTaskOptions internalOptions;
3899             CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
3900
3901             Task continuationTask = new ContinuationTaskFromTask(
3902                 this, continuationAction, null,
3903                 creationOptions, internalOptions,
3904                 ref stackMark
3905             );
3906
3907             // Register the continuation.  If synchronous execution is requested, this may
3908             // actually invoke the continuation before returning.
3909             ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
3910
3911             return continuationTask;
3912         }
3913         #endregion
3914
3915         #region Action<Task, Object> continuation
3916
3917         /// <summary>
3918         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
3919         /// </summary>
3920         /// <param name="continuationAction">
3921         /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
3922         /// passed the completed task as and the caller-supplied state object as arguments.
3923         /// </param>
3924         /// <param name="state">An object representing data to be used by the continuation action.</param>
3925         /// <returns>A new continuation <see cref="Task"/>.</returns>
3926         /// <remarks>
3927         /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
3928         /// completed, whether it completes due to running to completion successfully, faulting due to an
3929         /// unhandled exception, or exiting out early due to being canceled.
3930         /// </remarks>
3931         /// <exception cref="T:System.ArgumentNullException">
3932         /// The <paramref name="continuationAction"/> argument is null.
3933         /// </exception>
3934         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
3935         public Task ContinueWith(Action<Task, Object> continuationAction, Object state)
3936         {
3937             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
3938             return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
3939         }
3940
3941         /// <summary>
3942         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
3943         /// </summary>
3944         /// <param name="continuationAction">
3945         /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
3946         /// passed the completed task and the caller-supplied state object as arguments.
3947         /// </param>
3948         /// <param name="state">An object representing data to be used by the continuation action.</param>
3949         /// <param name="cancellationToken"> The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
3950         /// <returns>A new continuation <see cref="Task"/>.</returns>
3951         /// <remarks>
3952         /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
3953         /// completed, whether it completes due to running to completion successfully, faulting due to an
3954         /// unhandled exception, or exiting out early due to being canceled.
3955         /// </remarks>
3956         /// <exception cref="T:System.ArgumentNullException">
3957         /// The <paramref name="continuationAction"/> argument is null.
3958         /// </exception>
3959         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
3960         /// has already been disposed.
3961         /// </exception>
3962         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
3963         public Task ContinueWith(Action<Task, Object> continuationAction, Object state, CancellationToken cancellationToken)
3964         {
3965             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
3966             return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
3967         }
3968
3969         /// <summary>
3970         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
3971         /// </summary>
3972         /// <param name="continuationAction">
3973         /// An action to run when the <see cref="Task"/> completes.  When run, the delegate will be
3974         /// passed the completed task and the caller-supplied state object as arguments.
3975         /// </param>
3976         /// <param name="state">An object representing data to be used by the continuation action.</param>
3977         /// <param name="scheduler">
3978         /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
3979         /// </param>
3980         /// <returns>A new continuation <see cref="Task"/>.</returns>
3981         /// <remarks>
3982         /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
3983         /// completed, whether it completes due to running to completion successfully, faulting due to an
3984         /// unhandled exception, or exiting out early due to being canceled.
3985         /// </remarks>
3986         /// <exception cref="T:System.ArgumentNullException">
3987         /// The <paramref name="continuationAction"/> argument is null.
3988         /// </exception>
3989         /// <exception cref="T:System.ArgumentNullException">
3990         /// The <paramref name="scheduler"/> argument is null.
3991         /// </exception>
3992         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
3993         public Task ContinueWith(Action<Task, Object> continuationAction, Object state, TaskScheduler scheduler)
3994         {
3995             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
3996             return ContinueWith(continuationAction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
3997         }
3998
3999         /// <summary>
4000         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
4001         /// </summary>
4002         /// <param name="continuationAction">
4003         /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
4004         /// passed the completed task and the caller-supplied state object as arguments.
4005         /// </param>
4006         /// <param name="state">An object representing data to be used by the continuation action.</param>
4007         /// <param name="continuationOptions">
4008         /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
4009         /// as <see
4010         /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
4011         /// well as execution options, such as <see
4012         /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
4013         /// </param>
4014         /// <returns>A new continuation <see cref="Task"/>.</returns>
4015         /// <remarks>
4016         /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
4017         /// completed. If the continuation criteria specified through the <paramref
4018         /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled
4019         /// instead of scheduled.
4020         /// </remarks>
4021         /// <exception cref="T:System.ArgumentNullException">
4022         /// The <paramref name="continuationAction"/> argument is null.
4023         /// </exception>
4024         /// <exception cref="T:System.ArgumentOutOfRangeException">
4025         /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
4026         /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
4027         /// </exception>
4028         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
4029         public Task ContinueWith(Action<Task, Object> continuationAction, Object state, TaskContinuationOptions continuationOptions)
4030         {
4031             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
4032             return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
4033         }
4034
4035         /// <summary>
4036         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
4037         /// </summary>
4038         /// <param name="continuationAction">
4039         /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
4040         /// passed the completed task and the caller-supplied state object as arguments.
4041         /// </param>
4042         /// <param name="state">An object representing data to be used by the continuation action.</param>
4043         /// <param name="continuationOptions">
4044         /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
4045         /// as <see
4046         /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
4047         /// well as execution options, such as <see
4048         /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
4049         /// </param>
4050         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
4051         /// <param name="scheduler">
4052         /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
4053         /// execution.
4054         /// </param>
4055         /// <returns>A new continuation <see cref="Task"/>.</returns>
4056         /// <remarks>
4057         /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
4058         /// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
4059         /// are not met, the continuation task will be canceled instead of scheduled.
4060         /// </remarks>
4061         /// <exception cref="T:System.ArgumentNullException">
4062         /// The <paramref name="continuationAction"/> argument is null.
4063         /// </exception>
4064         /// <exception cref="T:System.ArgumentOutOfRangeException">
4065         /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
4066         /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
4067         /// </exception>
4068         /// <exception cref="T:System.ArgumentNullException">
4069         /// The <paramref name="scheduler"/> argument is null.
4070         /// </exception>
4071         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
4072         /// has already been disposed.
4073         /// </exception>
4074         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
4075         public Task ContinueWith(Action<Task, Object> continuationAction, Object state, CancellationToken cancellationToken,
4076                                  TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
4077         {
4078             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
4079             return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions, ref stackMark);
4080         }
4081
4082         // Same as the above overload, just with a stack mark parameter.
4083         private Task ContinueWith(Action<Task, Object> continuationAction, Object state, TaskScheduler scheduler,
4084             CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
4085         {
4086             // Throw on continuation with null action
4087             if (continuationAction == null)
4088             {
4089                 throw new ArgumentNullException("continuationAction");
4090             }
4091
4092             // Throw on continuation with null TaskScheduler
4093             if (scheduler == null)
4094             {
4095                 throw new ArgumentNullException("scheduler");
4096             }
4097             Contract.EndContractBlock();
4098
4099             TaskCreationOptions creationOptions;
4100             InternalTaskOptions internalOptions;
4101             CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
4102
4103             Task continuationTask = new ContinuationTaskFromTask(
4104                 this, continuationAction, state,
4105                 creationOptions, internalOptions,
4106                 ref stackMark
4107             );
4108
4109             // Register the continuation.  If synchronous execution is requested, this may
4110             // actually invoke the continuation before returning.
4111             ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
4112
4113             return continuationTask;
4114         }
4115
4116         #endregion
4117
4118         #region Func<Task, TResult> continuation
4119
4120         /// <summary>
4121         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
4122         /// </summary>
4123         /// <typeparam name="TResult">
4124         /// The type of the result produced by the continuation.
4125         /// </typeparam>
4126         /// <param name="continuationFunction">
4127         /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
4128         /// passed the completed task as an argument.
4129         /// </param>
4130         /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
4131         /// <remarks>
4132         /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
4133         /// completed, whether it completes due to running to completion successfully, faulting due to an
4134         /// unhandled exception, or exiting out early due to being canceled.
4135         /// </remarks>
4136         /// <exception cref="T:System.ArgumentNullException">
4137         /// The <paramref name="continuationFunction"/> argument is null.
4138         /// </exception>
4139         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
4140         public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction)
4141         {
4142             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
4143             return ContinueWith<TResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken),
4144                 TaskContinuationOptions.None, ref stackMark);
4145         }
4146
4147
4148         /// <summary>
4149         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
4150         /// </summary>
4151         /// <typeparam name="TResult">
4152         /// The type of the result produced by the continuation.
4153         /// </typeparam>
4154         /// <param name="continuationFunction">
4155         /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
4156         /// passed the completed task as an argument.
4157         /// </param>
4158         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
4159         /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
4160         /// <remarks>
4161         /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
4162         /// completed, whether it completes due to running to completion successfully, faulting due to an
4163         /// unhandled exception, or exiting out early due to being canceled.
4164         /// </remarks>
4165         /// <exception cref="T:System.ArgumentNullException">
4166         /// The <paramref name="continuationFunction"/> argument is null.
4167         /// </exception>
4168         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
4169         /// has already been disposed.
4170         /// </exception>
4171         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
4172         public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
4173         {
4174             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
4175             return ContinueWith<TResult>(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
4176         }
4177
4178         /// <summary>
4179         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
4180         /// </summary>
4181         /// <typeparam name="TResult">
4182         /// The type of the result produced by the continuation.
4183         /// </typeparam>
4184         /// <param name="continuationFunction">
4185         /// A function to run when the <see cref="Task"/> completes.  When run, the delegate will be
4186         /// passed the completed task as an argument.
4187         /// </param>
4188         /// <param name="scheduler">
4189         /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
4190         /// </param>
4191         /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
4192         /// <remarks>
4193         /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
4194         /// completed, whether it completes due to running to completion successfully, faulting due to an
4195         /// unhandled exception, or exiting out early due to being canceled.
4196         /// </remarks>
4197         /// <exception cref="T:System.ArgumentNullException">
4198         /// The <paramref name="continuationFunction"/> argument is null.
4199         /// </exception>
4200         /// <exception cref="T:System.ArgumentNullException">
4201         /// The <paramref name="scheduler"/> argument is null.
4202         /// </exception>
4203         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
4204         public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskScheduler scheduler)
4205         {
4206             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
4207             return ContinueWith<TResult>(continuationFunction, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
4208         }
4209
4210         /// <summary>
4211         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
4212         /// </summary>
4213         /// <typeparam name="TResult">
4214         /// The type of the result produced by the continuation.
4215         /// </typeparam>
4216         /// <param name="continuationFunction">
4217         /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
4218         /// passed the completed task as an argument.
4219         /// </param>
4220         /// <param name="continuationOptions">
4221         /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
4222         /// as <see
4223         /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
4224         /// well as execution options, such as <see
4225         /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
4226         /// </param>
4227         /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
4228         /// <remarks>
4229         /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
4230         /// completed. If the continuation criteria specified through the <paramref
4231         /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled
4232         /// instead of scheduled.
4233         /// </remarks>
4234         /// <exception cref="T:System.ArgumentNullException">
4235         /// The <paramref name="continuationFunction"/> argument is null.
4236         /// </exception>
4237         /// <exception cref="T:System.ArgumentOutOfRangeException">
4238         /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
4239         /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
4240         /// </exception>
4241         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
4242         public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
4243         {
4244             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
4245             return ContinueWith<TResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
4246         }
4247
4248         /// <summary>
4249         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
4250         /// </summary>
4251         /// <typeparam name="TResult">
4252         /// The type of the result produced by the continuation.
4253         /// </typeparam>
4254         /// <param name="continuationFunction">
4255         /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
4256         /// passed the completed task as an argument.
4257         /// </param>
4258         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
4259         /// <param name="continuationOptions">
4260         /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
4261         /// as <see
4262         /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
4263         /// well as execution options, such as <see
4264         /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
4265         /// </param>
4266         /// <param name="scheduler">
4267         /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
4268         /// execution.
4269         /// </param>
4270         /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
4271         /// <remarks>
4272         /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
4273         /// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
4274         /// are not met, the continuation task will be canceled instead of scheduled.
4275         /// </remarks>
4276         /// <exception cref="T:System.ArgumentNullException">
4277         /// The <paramref name="continuationFunction"/> argument is null.
4278         /// </exception>
4279         /// <exception cref="T:System.ArgumentOutOfRangeException">
4280         /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
4281         /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
4282         /// </exception>
4283         /// <exception cref="T:System.ArgumentNullException">
4284         /// The <paramref name="scheduler"/> argument is null.
4285         /// </exception>
4286         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
4287         /// has already been disposed.
4288         /// </exception>
4289         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
4290         public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, CancellationToken cancellationToken,
4291                                                    TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
4292         {
4293             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
4294             return ContinueWith<TResult>(continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
4295         }
4296
4297         // Same as the above overload, just with a stack mark parameter.
4298         private Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskScheduler scheduler,
4299             CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
4300         {
4301             // Throw on continuation with null function
4302             if (continuationFunction == null)
4303             {
4304                 throw new ArgumentNullException("continuationFunction");
4305             }
4306
4307             // Throw on continuation with null task scheduler
4308             if (scheduler == null)
4309             {
4310                 throw new ArgumentNullException("scheduler");
4311             }
4312             Contract.EndContractBlock();
4313
4314             TaskCreationOptions creationOptions;
4315             InternalTaskOptions internalOptions;
4316             CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
4317
4318             Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>(
4319                 this, continuationFunction, null,
4320                 creationOptions, internalOptions,
4321                 ref stackMark
4322             );
4323
4324             // Register the continuation.  If synchronous execution is requested, this may
4325             // actually invoke the continuation before returning.
4326             ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
4327
4328             return continuationTask;
4329         }
4330         #endregion
4331
4332         #region Func<Task, Object, TResult> continuation
4333
4334         /// <summary>
4335         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
4336         /// </summary>
4337         /// <typeparam name="TResult">
4338         /// The type of the result produced by the continuation.
4339         /// </typeparam>
4340         /// <param name="continuationFunction">
4341         /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
4342         /// passed the completed task and the caller-supplied state object as arguments.
4343         /// </param>
4344         /// <param name="state">An object representing data to be used by the continuation function.</param>
4345         /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
4346         /// <remarks>
4347         /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
4348         /// completed, whether it completes due to running to completion successfully, faulting due to an
4349         /// unhandled exception, or exiting out early due to being canceled.
4350         /// </remarks>
4351         /// <exception cref="T:System.ArgumentNullException">
4352         /// The <paramref name="continuationFunction"/> argument is null.
4353         /// </exception>
4354         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
4355         public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state)
4356         {
4357             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
4358             return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken),
4359                 TaskContinuationOptions.None, ref stackMark);
4360         }
4361
4362
4363         /// <summary>
4364         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
4365         /// </summary>
4366         /// <typeparam name="TResult">
4367         /// The type of the result produced by the continuation.
4368         /// </typeparam>
4369         /// <param name="continuationFunction">
4370         /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
4371         /// passed the completed task and the caller-supplied state object as arguments.
4372         /// </param>
4373         /// <param name="state">An object representing data to be used by the continuation function.</param>
4374         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
4375         /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
4376         /// <remarks>
4377         /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
4378         /// completed, whether it completes due to running to completion successfully, faulting due to an
4379         /// unhandled exception, or exiting out early due to being canceled.
4380         /// </remarks>
4381         /// <exception cref="T:System.ArgumentNullException">
4382         /// The <paramref name="continuationFunction"/> argument is null.
4383         /// </exception>
4384         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
4385         /// has already been disposed.
4386         /// </exception>
4387         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
4388         public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, CancellationToken cancellationToken)
4389         {
4390             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
4391             return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
4392         }
4393
4394         /// <summary>
4395         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
4396         /// </summary>
4397         /// <typeparam name="TResult">
4398         /// The type of the result produced by the continuation.
4399         /// </typeparam>
4400         /// <param name="continuationFunction">
4401         /// A function to run when the <see cref="Task"/> completes.  When run, the delegate will be
4402         /// passed the completed task and the caller-supplied state object as arguments.
4403         /// </param>
4404         /// <param name="state">An object representing data to be used by the continuation function.</param>
4405         /// <param name="scheduler">
4406         /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
4407         /// </param>
4408         /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
4409         /// <remarks>
4410         /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
4411         /// completed, whether it completes due to running to completion successfully, faulting due to an
4412         /// unhandled exception, or exiting out early due to being canceled.
4413         /// </remarks>
4414         /// <exception cref="T:System.ArgumentNullException">
4415         /// The <paramref name="continuationFunction"/> argument is null.
4416         /// </exception>
4417         /// <exception cref="T:System.ArgumentNullException">
4418         /// The <paramref name="scheduler"/> argument is null.
4419         /// </exception>
4420         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
4421         public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, TaskScheduler scheduler)
4422         {
4423             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
4424             return ContinueWith<TResult>(continuationFunction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
4425         }
4426
4427         /// <summary>
4428         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
4429         /// </summary>
4430         /// <typeparam name="TResult">
4431         /// The type of the result produced by the continuation.
4432         /// </typeparam>
4433         /// <param name="continuationFunction">
4434         /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
4435         /// passed the completed task and the caller-supplied state object as arguments.
4436         /// </param>
4437         /// <param name="state">An object representing data to be used by the continuation function.</param>
4438         /// <param name="continuationOptions">
4439         /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
4440         /// as <see
4441         /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
4442         /// well as execution options, such as <see
4443         /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
4444         /// </param>
4445         /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
4446         /// <remarks>
4447         /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
4448         /// completed. If the continuation criteria specified through the <paramref
4449         /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled
4450         /// instead of scheduled.
4451         /// </remarks>
4452         /// <exception cref="T:System.ArgumentNullException">
4453         /// The <paramref name="continuationFunction"/> argument is null.
4454         /// </exception>
4455         /// <exception cref="T:System.ArgumentOutOfRangeException">
4456         /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
4457         /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
4458         /// </exception>
4459         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
4460         public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, TaskContinuationOptions continuationOptions)
4461         {
4462             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
4463             return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
4464         }
4465
4466         /// <summary>
4467         /// Creates a continuation that executes when the target <see cref="Task"/> completes.
4468         /// </summary>
4469         /// <typeparam name="TResult">
4470         /// The type of the result produced by the continuation.
4471         /// </typeparam>
4472         /// <param name="continuationFunction">
4473         /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
4474         /// passed the completed task and the caller-supplied state object as arguments.
4475         /// </param>
4476         /// <param name="state">An object representing data to be used by the continuation function.</param>
4477         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
4478         /// <param name="continuationOptions">
4479         /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
4480         /// as <see
4481         /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
4482         /// well as execution options, such as <see
4483         /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
4484         /// </param>
4485         /// <param name="scheduler">
4486         /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
4487         /// execution.
4488         /// </param>
4489         /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
4490         /// <remarks>
4491         /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
4492         /// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
4493         /// are not met, the continuation task will be canceled instead of scheduled.
4494         /// </remarks>
4495         /// <exception cref="T:System.ArgumentNullException">
4496         /// The <paramref name="continuationFunction"/> argument is null.
4497         /// </exception>
4498         /// <exception cref="T:System.ArgumentOutOfRangeException">
4499         /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
4500         /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
4501         /// </exception>
4502         /// <exception cref="T:System.ArgumentNullException">
4503         /// The <paramref name="scheduler"/> argument is null.
4504         /// </exception>
4505         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
4506         /// has already been disposed.
4507         /// </exception>
4508         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
4509         public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, CancellationToken cancellationToken,
4510                                                    TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
4511         {
4512             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
4513             return ContinueWith<TResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions, ref stackMark);
4514         }
4515
4516         // Same as the above overload, just with a stack mark parameter.
4517         private Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, TaskScheduler scheduler,
4518             CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
4519         {
4520             // Throw on continuation with null function
4521             if (continuationFunction == null)
4522             {
4523                 throw new ArgumentNullException("continuationFunction");
4524             }
4525
4526             // Throw on continuation with null task scheduler
4527             if (scheduler == null)
4528             {
4529                 throw new ArgumentNullException("scheduler");
4530             }
4531             Contract.EndContractBlock();
4532
4533             TaskCreationOptions creationOptions;
4534             InternalTaskOptions internalOptions;
4535             CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
4536
4537             Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>(
4538                 this, continuationFunction, state,
4539                 creationOptions, internalOptions,
4540                 ref stackMark
4541             );
4542
4543             // Register the continuation.  If synchronous execution is requested, this may
4544             // actually invoke the continuation before returning.
4545             ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
4546
4547             return continuationTask;
4548         }
4549         #endregion
4550
4551         /// <summary>
4552         /// Converts TaskContinuationOptions to TaskCreationOptions, and also does
4553         /// some validity checking along the way.
4554         /// </summary>
4555         /// <param name="continuationOptions">Incoming TaskContinuationOptions</param>
4556         /// <param name="creationOptions">Outgoing TaskCreationOptions</param>
4557         /// <param name="internalOptions">Outgoing InternalTaskOptions</param>
4558         internal static void CreationOptionsFromContinuationOptions(
4559             TaskContinuationOptions continuationOptions,
4560             out TaskCreationOptions creationOptions,
4561             out InternalTaskOptions internalOptions)
4562         {
4563             // This is used a couple of times below
4564             TaskContinuationOptions NotOnAnything =
4565                 TaskContinuationOptions.NotOnCanceled |
4566                 TaskContinuationOptions.NotOnFaulted |
4567                 TaskContinuationOptions.NotOnRanToCompletion;
4568
4569             TaskContinuationOptions creationOptionsMask =
4570                 TaskContinuationOptions.PreferFairness |
4571                 TaskContinuationOptions.LongRunning |
4572                 TaskContinuationOptions.DenyChildAttach |
4573                 TaskContinuationOptions.HideScheduler |
4574                 TaskContinuationOptions.AttachedToParent|
4575                 TaskContinuationOptions.RunContinuationsAsynchronously;
4576
4577             // Check that LongRunning and ExecuteSynchronously are not specified together
4578             TaskContinuationOptions illegalMask = TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.LongRunning;
4579             if ((continuationOptions & illegalMask) == illegalMask)
4580             {
4581                 throw new ArgumentOutOfRangeException("continuationOptions", Environment.GetResourceString("Task_ContinueWith_ESandLR"));
4582             }
4583
4584             // Check that no illegal options were specified
4585             if ((continuationOptions &
4586                 ~(creationOptionsMask | NotOnAnything | 
4587                     TaskContinuationOptions.LazyCancellation | TaskContinuationOptions.ExecuteSynchronously)) != 0)
4588             {
4589                 throw new ArgumentOutOfRangeException("continuationOptions");
4590             }
4591
4592             // Check that we didn't specify "not on anything"
4593             if ((continuationOptions & NotOnAnything) == NotOnAnything)
4594             {
4595                 throw new ArgumentOutOfRangeException("continuationOptions", Environment.GetResourceString("Task_ContinueWith_NotOnAnything"));
4596             }
4597
4598             // This passes over all but LazyCancellation, which has no representation in TaskCreationOptions
4599             creationOptions = (TaskCreationOptions)(continuationOptions & creationOptionsMask);
4600
4601             // internalOptions has at least ContinuationTask ...
4602             internalOptions = InternalTaskOptions.ContinuationTask;
4603
4604             // ... and possibly LazyCancellation
4605             if ((continuationOptions & TaskContinuationOptions.LazyCancellation) != 0)
4606                 internalOptions |= InternalTaskOptions.LazyCancellation;
4607         }
4608
4609
4610         /// <summary>
4611         /// Registers the continuation and possibly runs it (if the task is already finished).
4612         /// </summary>
4613         /// <param name="continuationTask">The continuation task itself.</param>
4614         /// <param name="scheduler">TaskScheduler with which to associate continuation task.</param>
4615         /// <param name="options">Restrictions on when the continuation becomes active.</param>
4616         internal void ContinueWithCore(Task continuationTask,
4617                                        TaskScheduler scheduler,
4618                                        CancellationToken cancellationToken,
4619                                        TaskContinuationOptions options)
4620         {
4621             Contract.Requires(continuationTask != null, "Task.ContinueWithCore(): null continuationTask");
4622             Contract.Requires(scheduler != null, "Task.ContinueWithCore(): null scheduler");
4623             Contract.Requires(!continuationTask.IsCompleted, "Did not expect continuationTask to be completed");
4624
4625             // Create a TaskContinuation
4626             TaskContinuation continuation = new StandardTaskContinuation(continuationTask, options, scheduler);
4627
4628             // If cancellationToken is cancellable, then assign it.  
4629             if (cancellationToken.CanBeCanceled)
4630             {
4631                 if (IsCompleted || cancellationToken.IsCancellationRequested)
4632                 {
4633                     // If the antecedent has completed, then we will not be queuing up
4634                     // the continuation in the antecedent's continuation list.  Likewise,
4635                     // if the cancellationToken has been canceled, continuationTask will
4636                     // be completed in the AssignCancellationToken call below, and there
4637                     // is no need to queue the continuation to the antecedent's continuation
4638                     // list.  In either of these two cases, we will pass "null" for the antecedent,
4639                     // meaning "the cancellation callback should not attempt to remove the
4640                     // continuation from its antecedent's continuation list".
4641                     continuationTask.AssignCancellationToken(cancellationToken, null, null);
4642                 }
4643                 else
4644                 {
4645                     // The antecedent is not yet complete, so there is a pretty good chance
4646                     // that the continuation will be queued up in the antecedent.  Assign the
4647                     // cancellation token with information about the antecedent, so that the
4648                     // continuation can be dequeued upon the signalling of the token.
4649                     //
4650                     // It's possible that the antecedent completes before the call to AddTaskContinuation,
4651                     // and that is a benign ----.  It just means that the cancellation will result in
4652                     // a futile search of the antecedent's continuation list.
4653                     continuationTask.AssignCancellationToken(cancellationToken, this, continuation);
4654                 }
4655             }
4656
4657             // In the case of a pre-canceled token, continuationTask will have been completed
4658             // in a Canceled state by now.  If such is the case, there is no need to go through
4659             // the motions of queuing up the continuation for eventual execution.
4660             if (!continuationTask.IsCompleted)
4661             {
4662                 // We need additional correlation produced here to ensure that at least the continuation 
4663                 // code will be correlatable to the currrent activity that initiated "this" task:
4664                 //  . when the antecendent ("this") is a promise we have very little control over where 
4665                 //    the code for the promise will run (e.g. it can be a task from a user provided 
4666                 //    TaskCompletionSource or from a classic Begin/End async operation); this user or 
4667                 //    system code will likely not have stamped an activity id on the thread, so there's
4668                 //    generally no easy correlation that can be provided between the current activity
4669                 //    and the promise. Also the continuation code may run practically on any thread. 
4670                 //    Since there may be no correlation between the current activity and the TCS's task
4671                 //    activity, we ensure we at least create a correlation from the current activity to
4672                 //    the continuation that runs when the promise completes.
4673                 if ((this.Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0 &&
4674                     !(this is ITaskCompletionAction))
4675                 {
4676                     var etwLog = TplEtwProvider.Log;
4677                     if (etwLog.IsEnabled())
4678                     {
4679                         etwLog.AwaitTaskContinuationScheduled(TaskScheduler.Current.Id, Task.CurrentId ?? 0, continuationTask.Id);
4680                     }
4681                 }
4682
4683                 // Attempt to enqueue the continuation
4684                 bool continuationQueued = AddTaskContinuation(continuation, addBeforeOthers: false);
4685
4686                 // If the continuation was not queued (because the task completed), then run it now.
4687                 if (!continuationQueued) continuation.Run(this, bCanInlineContinuationTask: true);
4688             }
4689         }
4690         #endregion
4691
4692         // Adds a lightweight completion action to a task.  This is similar to a continuation
4693         // task except that it is stored as an action, and thus does not require the allocation/
4694         // execution resources of a continuation task.
4695         //
4696         // Used internally by ContinueWhenAll() and ContinueWhenAny().
4697         internal void AddCompletionAction(ITaskCompletionAction action)
4698         {
4699             AddCompletionAction(action, addBeforeOthers: false);
4700         }
4701
4702         private void AddCompletionAction(ITaskCompletionAction action, bool addBeforeOthers)
4703         {
4704             if (!AddTaskContinuation(action, addBeforeOthers))
4705                 action.Invoke(this); // run the action directly if we failed to queue the continuation (i.e., the task completed)
4706         }
4707
4708         // Support method for AddTaskContinuation that takes care of multi-continuation logic.
4709         // Returns true if and only if the continuation was successfully queued.
4710         // THIS METHOD ASSUMES THAT m_continuationObject IS NOT NULL.  That case was taken
4711         // care of in the calling method, AddTaskContinuation().
4712         private bool AddTaskContinuationComplex(object tc, bool addBeforeOthers)
4713         {
4714             Contract.Requires(tc != null, "Expected non-null tc object in AddTaskContinuationComplex");
4715
4716             object oldValue = m_continuationObject;
4717
4718             // Logic for the case where we were previously storing a single continuation
4719             if ((oldValue != s_taskCompletionSentinel) && (!(oldValue is List<object>)))
4720             {
4721                 // Construct a new TaskContinuation list
4722                 List<object> newList = new List<object>();
4723
4724                 // Add in the old single value
4725                 newList.Add(oldValue);
4726
4727                 // Now CAS in the new list
4728                 Interlocked.CompareExchange(ref m_continuationObject, newList, oldValue);
4729
4730                 // We might be racing against another thread converting the single into
4731                 // a list, or we might be racing against task completion, so resample "list"
4732                 // below.
4733             }
4734
4735             // m_continuationObject is guaranteed at this point to be either a List or
4736             // s_taskCompletionSentinel.
4737             List<object> list = m_continuationObject as List<object>;
4738             Contract.Assert((list != null) || (m_continuationObject == s_taskCompletionSentinel),
4739                 "Expected m_continuationObject to be list or sentinel");
4740
4741             // If list is null, it can only mean that s_taskCompletionSentinel has been exchanged
4742             // into m_continuationObject.  Thus, the task has completed and we should return false
4743             // from this method, as we will not be queuing up the continuation.
4744             if (list != null)
4745             {
4746                 lock (list)
4747                 {
4748                     // It is possible for the task to complete right after we snap the copy of
4749                     // the list.  If so, then fall through and return false without queuing the
4750                     // continuation.
4751                     if (m_continuationObject != s_taskCompletionSentinel)
4752                     {
4753                         // Before growing the list we remove possible null entries that are the
4754                         // result from RemoveContinuations()
4755                         if (list.Count == list.Capacity)
4756                         {
4757                             list.RemoveAll(s_IsTaskContinuationNullPredicate);
4758                         }
4759
4760                         if (addBeforeOthers)
4761                             list.Insert(0, tc);
4762                         else
4763                             list.Add(tc);
4764
4765                         return true; // continuation successfully queued, so return true.
4766                     }
4767                 }
4768             }
4769
4770             // We didn't succeed in queuing the continuation, so return false.
4771             return false;
4772         }
4773
4774         // Record a continuation task or action.
4775         // Return true if and only if we successfully queued a continuation.
4776         private bool AddTaskContinuation(object tc, bool addBeforeOthers)
4777         {
4778             Contract.Requires(tc != null);
4779
4780             // Make sure that, if someone calls ContinueWith() right after waiting for the predecessor to complete,
4781             // we don't queue up a continuation.
4782             if (IsCompleted) return false;
4783
4784             // Try to just jam tc into m_continuationObject
4785             if ((m_continuationObject != null) || (Interlocked.CompareExchange(ref m_continuationObject, tc, null) != null))
4786             {
4787                 // If we get here, it means that we failed to CAS tc into m_continuationObject.
4788                 // Therefore, we must go the more complicated route.
4789                 return AddTaskContinuationComplex(tc, addBeforeOthers);
4790             }
4791             else return true;
4792         }
4793
4794         // Removes a continuation task from m_continuations
4795         internal void RemoveContinuation(object continuationObject) // could be TaskContinuation or Action<Task>
4796         {
4797             // We need to snap a local reference to m_continuations since reading a volatile object is more costly.
4798             // Also to prevent the value to be changed as result of a race condition with another method.
4799             object continuationsLocalRef = m_continuationObject;
4800
4801             // Task is completed. Nothing to do here.
4802             if (continuationsLocalRef == s_taskCompletionSentinel) return;
4803
4804             List<object> continuationsLocalListRef = continuationsLocalRef as List<object>;
4805
4806             if (continuationsLocalListRef == null)
4807             {
4808                 // This is not a list. If we have a single object (the one we want to remove) we try to replace it with an empty list.
4809                 // Note we cannot go back to a null state, since it will mess up the AddTaskContinuation logic.
4810                 if (Interlocked.CompareExchange(ref m_continuationObject, new List<object>(), continuationObject) != continuationObject)
4811                 {
4812                     // If we fail it means that either AddContinuationComplex won the race condition and m_continuationObject is now a List
4813                     // that contains the element we want to remove. Or FinishContinuations set the s_taskCompletionSentinel.
4814                     // So we should try to get a list one more time
4815                     continuationsLocalListRef = m_continuationObject as List<object>;
4816                 }
4817                 else
4818                 {
4819                     // Exchange was successful so we can skip the last comparison
4820                     return;
4821                 }
4822             }
4823
4824             // if continuationsLocalRef == null it means s_taskCompletionSentinel has been set already and there is nothing else to do.
4825             if (continuationsLocalListRef != null)
4826             {
4827                 lock (continuationsLocalListRef)
4828                 {
4829                     // There is a small chance that this task completed since we took a local snapshot into
4830                     // continuationsLocalRef.  In that case, just return; we don't want to be manipulating the
4831                     // continuation list as it is being processed.
4832                     if (m_continuationObject == s_taskCompletionSentinel) return;
4833
4834                     // Find continuationObject in the continuation list
4835                     int index = continuationsLocalListRef.IndexOf(continuationObject);
4836
4837                     if (index != -1)
4838                     {
4839                         // null out that TaskContinuation entry, which will be interpreted as "to be cleaned up"
4840                         continuationsLocalListRef[index] = null;
4841
4842                     }
4843                 }
4844             }
4845         }
4846
4847         // statically allocated delegate for the RemoveAll expression in RemoveContinuations() and AddContinuationComplex()
4848         private readonly static Predicate<object> s_IsTaskContinuationNullPredicate =
4849             new Predicate<object>((tc) => { return (tc == null); });
4850
4851
4852         //
4853         // Wait methods
4854         //
4855
4856         /// <summary>
4857         /// Waits for all of the provided <see cref="Task"/> objects to complete execution.
4858         /// </summary>
4859         /// <param name="tasks">
4860         /// An array of <see cref="Task"/> instances on which to wait.
4861         /// </param>
4862         /// <exception cref="T:System.ArgumentNullException">
4863         /// The <paramref name="tasks"/> argument is null.
4864         /// </exception>
4865         /// <exception cref="T:System.ArgumentNullException">
4866         /// The <paramref name="tasks"/> argument contains a null element.
4867         /// </exception>
4868         /// <exception cref="T:System.AggregateException">
4869         /// At least one of the <see cref="Task"/> instances was canceled -or- an exception was thrown during
4870         /// the execution of at least one of the <see cref="Task"/> instances.
4871         /// </exception>
4872         [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
4873         public static void WaitAll(params Task[] tasks)
4874         {
4875 #if DEBUG
4876             bool waitResult =
4877 #endif
4878             WaitAll(tasks, Timeout.Infinite);
4879
4880 #if DEBUG
4881             Contract.Assert(waitResult, "expected wait to succeed");
4882 #endif
4883         }
4884
4885         /// <summary>
4886         /// Waits for all of the provided <see cref="Task"/> objects to complete execution.
4887         /// </summary>
4888         /// <returns>
4889         /// true if all of the <see cref="Task"/> instances completed execution within the allotted time;
4890         /// otherwise, false.
4891         /// </returns>
4892         /// <param name="tasks">
4893         /// An array of <see cref="Task"/> instances on which to wait.
4894         /// </param>
4895         /// <param name="timeout">
4896         /// A <see cref="System.TimeSpan"/> that represents the number of milliseconds to wait, or a <see
4897         /// cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
4898         /// </param>
4899         /// <exception cref="T:System.ArgumentNullException">
4900         /// The <paramref name="tasks"/> argument is null.
4901         /// </exception>
4902         /// <exception cref="T:System.ArgumentException">
4903         /// The <paramref name="tasks"/> argument contains a null element.
4904         /// </exception>
4905         /// <exception cref="T:System.AggregateException">
4906         /// At least one of the <see cref="Task"/> instances was canceled -or- an exception was thrown during
4907         /// the execution of at least one of the <see cref="Task"/> instances.
4908         /// </exception>
4909         /// <exception cref="T:System.ArgumentOutOfRangeException">
4910         /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents an
4911         /// infinite time-out -or- timeout is greater than
4912         /// <see cref="System.Int32.MaxValue"/>.
4913         /// </exception>
4914         [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
4915         public static bool WaitAll(Task[] tasks, TimeSpan timeout)
4916         {
4917             long totalMilliseconds = (long)timeout.TotalMilliseconds;
4918             if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
4919             {
4920                 throw new ArgumentOutOfRangeException("timeout");
4921             }
4922
4923             return WaitAll(tasks, (int)totalMilliseconds);
4924
4925         }
4926
4927         /// <summary>
4928         /// Waits for all of the provided <see cref="Task"/> objects to complete execution.
4929         /// </summary>
4930         /// <returns>
4931         /// true if all of the <see cref="Task"/> instances completed execution within the allotted time;
4932         /// otherwise, false.
4933         /// </returns>
4934         /// <param name="millisecondsTimeout">
4935         /// The number of milliseconds to wait, or <see cref="System.Threading.Timeout.Infinite"/> (-1) to
4936         /// wait indefinitely.</param>
4937         /// <param name="tasks">An array of <see cref="Task"/> instances on which to wait.
4938         /// </param>
4939         /// <exception cref="T:System.ArgumentNullException">
4940         /// The <paramref name="tasks"/> argument is null.
4941         /// </exception>
4942         /// <exception cref="T:System.ArgumentException">
4943         /// The <paramref name="tasks"/> argument contains a null element.
4944         /// </exception>
4945         /// <exception cref="T:System.AggregateException">
4946         /// At least one of the <see cref="Task"/> instances was canceled -or- an exception was thrown during
4947         /// the execution of at least one of the <see cref="Task"/> instances.
4948         /// </exception>
4949         /// <exception cref="T:System.ArgumentOutOfRangeException">
4950         /// <paramref name="millisecondsTimeout"/> is a negative number other than -1, which represents an
4951         /// infinite time-out.
4952         /// </exception>
4953         [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
4954         public static bool WaitAll(Task[] tasks, int millisecondsTimeout)
4955         {
4956             return WaitAll(tasks, millisecondsTimeout, default(CancellationToken));
4957         }
4958
4959         /// <summary>
4960         /// Waits for all of the provided <see cref="Task"/> objects to complete execution.
4961         /// </summary>
4962         /// <returns>
4963         /// true if all of the <see cref="Task"/> instances completed execution within the allotted time;
4964         /// otherwise, false.
4965         /// </returns>
4966         /// <param name="tasks">
4967         /// An array of <see cref="Task"/> instances on which to wait.
4968         /// </param>
4969         /// <param name="cancellationToken">
4970         /// A <see cref="CancellationToken"/> to observe while waiting for the tasks to complete.
4971         /// </param>
4972         /// <exception cref="T:System.ArgumentNullException">
4973         /// The <paramref name="tasks"/> argument is null.
4974         /// </exception>
4975         /// <exception cref="T:System.ArgumentException">
4976         /// The <paramref name="tasks"/> argument contains a null element.
4977         /// </exception>
4978         /// <exception cref="T:System.AggregateException">
4979         /// At least one of the <see cref="Task"/> instances was canceled -or- an exception was thrown during
4980         /// the execution of at least one of the <see cref="Task"/> instances.
4981         /// </exception>
4982         /// <exception cref="T:System.OperationCanceledException">
4983         /// The <paramref name="cancellationToken"/> was canceled.
4984         /// </exception>
4985         [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
4986         public static void WaitAll(Task[] tasks, CancellationToken cancellationToken)
4987         {
4988             WaitAll(tasks, Timeout.Infinite, cancellationToken);
4989         }
4990
4991         /// <summary>
4992         /// Waits for all of the provided <see cref="Task"/> objects to complete execution.
4993         /// </summary>
4994         /// <returns>
4995         /// true if all of the <see cref="Task"/> instances completed execution within the allotted time;
4996         /// otherwise, false.
4997         /// </returns>
4998         /// <param name="tasks">
4999         /// An array of <see cref="Task"/> instances on which to wait.
5000         /// </param>
5001         /// <param name="millisecondsTimeout">
5002         /// The number of milliseconds to wait, or <see cref="System.Threading.Timeout.Infinite"/> (-1) to
5003         /// wait indefinitely.
5004         /// </param>
5005         /// <param name="cancellationToken">
5006         /// A <see cref="CancellationToken"/> to observe while waiting for the tasks to complete.
5007         /// </param>
5008         /// <exception cref="T:System.ArgumentNullException">
5009         /// The <paramref name="tasks"/> argument is null.
5010         /// </exception>
5011         /// <exception cref="T:System.ArgumentException">
5012         /// The <paramref name="tasks"/> argument contains a null element.
5013         /// </exception>
5014         /// <exception cref="T:System.AggregateException">
5015         /// At least one of the <see cref="Task"/> instances was canceled -or- an exception was thrown during
5016         /// the execution of at least one of the <see cref="Task"/> instances.
5017         /// </exception>
5018         /// <exception cref="T:System.ArgumentOutOfRangeException">
5019         /// <paramref name="millisecondsTimeout"/> is a negative number other than -1, which represents an
5020         /// infinite time-out.
5021         /// </exception>
5022         /// <exception cref="T:System.OperationCanceledException">
5023         /// The <paramref name="cancellationToken"/> was canceled.
5024         /// </exception>
5025         [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
5026         public static bool WaitAll(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
5027         {
5028             if (tasks == null)
5029             {
5030                 throw new ArgumentNullException("tasks");
5031             }
5032             if (millisecondsTimeout < -1)
5033             {
5034                 throw new ArgumentOutOfRangeException("millisecondsTimeout");
5035             }
5036             Contract.EndContractBlock();
5037
5038             cancellationToken.ThrowIfCancellationRequested(); // early check before we make any allocations
5039
5040             //
5041             // In this WaitAll() implementation we have 2 alternate code paths for a task to be handled:
5042             // CODEPATH1: skip an already completed task, CODEPATH2: actually wait on tasks
5043             // We make sure that the exception behavior of Task.Wait() is replicated the same for tasks handled in either of these codepaths
5044             //
5045
5046             List<Exception> exceptions = null;
5047             List<Task> waitedOnTaskList = null;
5048             List<Task> notificationTasks = null;
5049
5050             // If any of the waited-upon tasks end as Faulted or Canceled, set these to true.
5051             bool exceptionSeen = false, cancellationSeen = false;
5052
5053             bool returnValue = true;
5054
5055             // Collects incomplete tasks in "waitedOnTaskList"
5056             for (int i = tasks.Length - 1; i >= 0; i--)
5057             {
5058                 Task task = tasks[i];
5059
5060                 if (task == null)
5061                 {
5062                     throw new ArgumentException(Environment.GetResourceString("Task_WaitMulti_NullTask"), "tasks");
5063                 }
5064
5065                 bool taskIsCompleted = task.IsCompleted;
5066                 if (!taskIsCompleted)
5067                 {
5068                     // try inlining the task only if we have an infinite timeout and an empty cancellation token
5069                     if (millisecondsTimeout != Timeout.Infinite || cancellationToken.CanBeCanceled)
5070                     {
5071                         // We either didn't attempt inline execution because we had a non-infinite timeout or we had a cancellable token.
5072                         // In all cases we need to do a full wait on the task (=> add its event into the list.)
5073                         AddToList(task, ref waitedOnTaskList, initSize: tasks.Length);
5074                     }
5075                     else
5076                     {
5077                         // We are eligible for inlining.  If it doesn't work, we'll do a full wait.
5078                         taskIsCompleted = task.WrappedTryRunInline() && task.IsCompleted; // A successful TryRunInline doesn't guarantee completion
5079                         if (!taskIsCompleted) AddToList(task, ref waitedOnTaskList, initSize: tasks.Length);
5080                     }
5081                 }
5082
5083                 if (taskIsCompleted)
5084                 {
5085                     if (task.IsFaulted) exceptionSeen = true;
5086                     else if (task.IsCanceled) cancellationSeen = true;
5087                     if (task.IsWaitNotificationEnabled) AddToList(task, ref notificationTasks, initSize: 1);
5088                 }
5089             }
5090
5091             if (waitedOnTaskList != null)
5092             {
5093                 // Block waiting for the tasks to complete.
5094                 returnValue = WaitAllBlockingCore(waitedOnTaskList, millisecondsTimeout, cancellationToken);
5095
5096                 // If the wait didn't time out, ensure exceptions are propagated, and if a debugger is
5097                 // attached and one of these tasks requires it, that we notify the debugger of a wait completion.
5098                 if (returnValue)
5099                 {
5100                     // Add any exceptions for this task to the collection, and if it's wait
5101                     // notification bit is set, store it to operate on at the end.
5102                     foreach (var task in waitedOnTaskList)
5103                     {
5104                         if (task.IsFaulted) exceptionSeen = true;
5105                         else if (task.IsCanceled) cancellationSeen = true;
5106                         if (task.IsWaitNotificationEnabled) AddToList(task, ref notificationTasks, initSize: 1);
5107                     }
5108                 }
5109
5110                 // We need to prevent the tasks array from being GC'ed until we come out of the wait.
5111                 // This is necessary so that the Parallel Debugger can traverse it during the long wait and 
5112                 // deduce waiter/waitee relationships
5113                 GC.KeepAlive(tasks);
5114             }
5115
5116             // Now that we're done and about to exit, if the wait completed and if we have 
5117             // any tasks with a notification bit set, signal the debugger if any requires it.
5118             if (returnValue && notificationTasks != null)
5119             {
5120                 // Loop through each task tha that had its bit set, and notify the debugger
5121                 // about the first one that requires it.  The debugger will reset the bit
5122                 // for any tasks we don't notify of as soon as we break, so we only need to notify
5123                 // for one.
5124                 foreach (var task in notificationTasks)
5125                 {
5126                     if (task.NotifyDebuggerOfWaitCompletionIfNecessary()) break;
5127                 }
5128             }
5129
5130             // If one or more threw exceptions, aggregate and throw them.
5131             if (returnValue && (exceptionSeen || cancellationSeen))
5132             {
5133                 // If the WaitAll was canceled and tasks were canceled but not faulted, 
5134                 // prioritize throwing an OCE for canceling the WaitAll over throwing an 
5135                 // AggregateException for all of the canceled Tasks.  This helps
5136                 // to bring determinism to an otherwise non-determistic case of using
5137                 // the same token to cancel both the WaitAll and the Tasks.
5138                 if (!exceptionSeen) cancellationToken.ThrowIfCancellationRequested();
5139
5140                 // Now gather up and throw all of the exceptions.
5141                 foreach (var task in tasks) AddExceptionsForCompletedTask(ref exceptions, task);
5142                 Contract.Assert(exceptions != null, "Should have seen at least one exception");
5143                 throw new AggregateException(exceptions);
5144             }
5145
5146             return returnValue;
5147         }
5148
5149         /// <summary>Adds an element to the list, initializing the list if it's null.</summary>
5150         /// <typeparam name="T">Specifies the type of data stored in the list.</typeparam>
5151         /// <param name="item">The item to add.</param>
5152         /// <param name="list">The list.</param>
5153         /// <param name="initSize">The size to which to initialize the list if the list is null.</param>
5154         private static void AddToList<T>(T item, ref List<T> list, int initSize)
5155         {
5156             if (list == null) list = new List<T>(initSize);
5157             list.Add(item);
5158         }
5159
5160         /// <summary>Performs a blocking WaitAll on the vetted list of tasks.</summary>
5161         /// <param name="tasks">The tasks, which have already been checked and filtered for completion.</param>
5162         /// <param name="millisecondsTimeout">The timeout.</param>
5163         /// <param name="cancellationToken">The cancellation token.</param>
5164         /// <returns>true if all of the tasks completed; otherwise, false.</returns>
5165         private static bool WaitAllBlockingCore(List<Task> tasks, int millisecondsTimeout, CancellationToken cancellationToken)
5166         {
5167             Contract.Assert(tasks != null, "Expected a non-null list of tasks");
5168             Contract.Assert(tasks.Count > 0, "Expected at least one task");
5169
5170             bool waitCompleted = false;
5171             var mres = new SetOnCountdownMres(tasks.Count);
5172             try
5173             {
5174                 foreach (var task in tasks)
5175                 {
5176                     task.AddCompletionAction(mres, addBeforeOthers: true);
5177                 }
5178                 waitCompleted = mres.Wait(millisecondsTimeout, cancellationToken);
5179             }
5180             finally
5181             {
5182                 if (!waitCompleted)
5183                 {
5184                     foreach (var task in tasks)
5185                     {
5186                         if (!task.IsCompleted) task.RemoveContinuation(mres);
5187                     }
5188                 }
5189                 // It's ok that we don't dispose of the MRES here, as we never
5190                 // access the MRES' WaitHandle, and thus no finalizable resources
5191                 // are actually created.  We don't always just Dispose it because
5192                 // a continuation that's accessing the MRES could still be executing.
5193             }
5194             return waitCompleted;
5195         }
5196
5197         // A ManualResetEventSlim that will get Set after Invoke is called count times.
5198         // This allows us to replace this logic:
5199         //      var mres = new ManualResetEventSlim(tasks.Count);
5200         //      Action<Task> completionAction = delegate { if(Interlocked.Decrement(ref count) == 0) mres.Set(); };
5201         //      foreach(var task in tasks) task.AddCompletionAction(completionAction);
5202         // with this logic:
5203         //      var mres = new SetOnCountdownMres(tasks.Count);
5204         //      foreach(var task in tasks) task.AddCompletionAction(mres);
5205         // which saves a couple of allocations.
5206         //
5207         // Used in WaitAllBlockingCore (above).
5208         private sealed class SetOnCountdownMres : ManualResetEventSlim, ITaskCompletionAction
5209         {
5210             private int _count;
5211
5212             internal SetOnCountdownMres(int count)
5213             {
5214                 Contract.Assert(count > 0, "Expected count > 0");
5215                 _count = count;
5216             }
5217
5218             public void Invoke(Task completingTask)
5219             {
5220                 if (Interlocked.Decrement(ref _count) == 0) Set();
5221                 Contract.Assert(_count >= 0, "Count should never go below 0");
5222             }
5223         }
5224
5225         /// <summary>
5226         /// Internal WaitAll implementation which is meant to be used with small number of tasks,
5227         /// optimized for Parallel.Invoke and other structured primitives.
5228         /// </summary>
5229         internal static void FastWaitAll(Task[] tasks)
5230         {
5231             Contract.Requires(tasks != null);
5232
5233             List<Exception> exceptions = null;
5234
5235             // Collects incomplete tasks in "waitedOnTaskList" and their cooperative events in "cooperativeEventList"
5236             for (int i = tasks.Length - 1; i >= 0; i--)
5237             {
5238                 if (!tasks[i].IsCompleted)
5239                 {
5240                     // Just attempting to inline here... result doesn't matter.
5241                     // We'll do a second pass to do actual wait on each task, and to aggregate their exceptions.
5242                     // If the task is inlined here, it will register as IsCompleted in the second pass
5243                     // and will just give us the exception.
5244                     tasks[i].WrappedTryRunInline();
5245                 }
5246             }
5247
5248             // Wait on the tasks.
5249             for (int i = tasks.Length - 1; i >= 0; i--)
5250             {
5251                 var task = tasks[i];
5252                 task.SpinThenBlockingWait(Timeout.Infinite, default(CancellationToken));
5253                 AddExceptionsForCompletedTask(ref exceptions, task);
5254
5255                 // Note that unlike other wait code paths, we do not check
5256                 // task.NotifyDebuggerOfWaitCompletionIfNecessary() here, because this method is currently
5257                 // only used from contexts where the tasks couldn't have that bit set, namely
5258                 // Parallel.Invoke.  If that ever changes, such checks should be added here.
5259             }
5260
5261             // If one or more threw exceptions, aggregate them.
5262             if (exceptions != null)
5263             {
5264                 throw new AggregateException(exceptions);
5265             }
5266         }
5267
5268         /// <summary>
5269         /// This internal function is only meant to be called by WaitAll()
5270         /// If the completed task is canceled or it has other exceptions, here we will add those
5271         /// into the passed in exception list (which will be lazily initialized here).
5272         /// </summary>
5273         internal static void AddExceptionsForCompletedTask(ref List<Exception> exceptions, Task t)
5274         {
5275             AggregateException ex = t.GetExceptions(true);
5276             if (ex != null)
5277             {
5278                 // make sure the task's exception observed status is set appropriately
5279                 // it's possible that WaitAll was called by the parent of an attached child,
5280                 // this will make sure it won't throw again in the implicit wait
5281                 t.UpdateExceptionObservedStatus();
5282
5283                 if (exceptions == null)
5284                 {
5285                     exceptions = new List<Exception>(ex.InnerExceptions.Count);
5286                 }
5287
5288                 exceptions.AddRange(ex.InnerExceptions);
5289             }
5290         }
5291
5292
5293         /// <summary>
5294         /// Waits for any of the provided <see cref="Task"/> objects to complete execution.
5295         /// </summary>
5296         /// <param name="tasks">
5297         /// An array of <see cref="Task"/> instances on which to wait.
5298         /// </param>
5299         /// <returns>The index of the completed task in the <paramref name="tasks"/> array argument.</returns>
5300         /// <exception cref="T:System.ArgumentNullException">
5301         /// The <paramref name="tasks"/> argument is null.
5302         /// </exception>
5303         /// <exception cref="T:System.ArgumentException">
5304         /// The <paramref name="tasks"/> argument contains a null element.
5305         /// </exception>
5306         [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
5307         public static int WaitAny(params Task[] tasks)
5308         {
5309             int waitResult = WaitAny(tasks, Timeout.Infinite);
5310             Contract.Assert(tasks.Length == 0 || waitResult != -1, "expected wait to succeed");
5311             return waitResult;
5312         }
5313
5314         /// <summary>
5315         /// Waits for any of the provided <see cref="Task"/> objects to complete execution.
5316         /// </summary>
5317         /// <param name="tasks">
5318         /// An array of <see cref="Task"/> instances on which to wait.
5319         /// </param>
5320         /// <param name="timeout">
5321         /// A <see cref="System.TimeSpan"/> that represents the number of milliseconds to wait, or a <see
5322         /// cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
5323         /// </param>
5324         /// <returns>
5325         /// The index of the completed task in the <paramref name="tasks"/> array argument, or -1 if the
5326         /// timeout occurred.
5327         /// </returns>
5328         /// <exception cref="T:System.ArgumentNullException">
5329         /// The <paramref name="tasks"/> argument is null.
5330         /// </exception>
5331         /// <exception cref="T:System.ArgumentException">
5332         /// The <paramref name="tasks"/> argument contains a null element.
5333         /// </exception>
5334         /// <exception cref="T:System.ArgumentOutOfRangeException">
5335         /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents an
5336         /// infinite time-out -or- timeout is greater than
5337         /// <see cref="System.Int32.MaxValue"/>.
5338         /// </exception>
5339         [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
5340         public static int WaitAny(Task[] tasks, TimeSpan timeout)
5341         {
5342             long totalMilliseconds = (long)timeout.TotalMilliseconds;
5343             if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
5344             {
5345                 throw new ArgumentOutOfRangeException("timeout");
5346             }
5347
5348             return WaitAny(tasks, (int)totalMilliseconds);
5349         }
5350
5351         /// <summary>
5352         /// Waits for any of the provided <see cref="Task"/> objects to complete execution.
5353         /// </summary>
5354         /// <param name="tasks">
5355         /// An array of <see cref="Task"/> instances on which to wait.
5356         /// </param>
5357         /// <param name="cancellationToken">
5358         /// A <see cref="CancellationToken"/> to observe while waiting for a task to complete.
5359         /// </param>
5360         /// <returns>
5361         /// The index of the completed task in the <paramref name="tasks"/> array argument.
5362         /// </returns>
5363         /// <exception cref="T:System.ArgumentNullException">
5364         /// The <paramref name="tasks"/> argument is null.
5365         /// </exception>
5366         /// <exception cref="T:System.ArgumentException">
5367         /// The <paramref name="tasks"/> argument contains a null element.
5368         /// </exception>
5369         /// <exception cref="T:System.OperationCanceledException">
5370         /// The <paramref name="cancellationToken"/> was canceled.
5371         /// </exception>
5372         [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
5373         public static int WaitAny(Task[] tasks, CancellationToken cancellationToken)
5374         {
5375             return WaitAny(tasks, Timeout.Infinite, cancellationToken);
5376         }
5377
5378         /// <summary>
5379         /// Waits for any of the provided <see cref="Task"/> objects to complete execution.
5380         /// </summary>
5381         /// <param name="tasks">
5382         /// An array of <see cref="Task"/> instances on which to wait.
5383         /// </param>
5384         /// <param name="millisecondsTimeout">
5385         /// The number of milliseconds to wait, or <see cref="System.Threading.Timeout.Infinite"/> (-1) to
5386         /// wait indefinitely.
5387         /// </param>
5388         /// <returns>
5389         /// The index of the completed task in the <paramref name="tasks"/> array argument, or -1 if the
5390         /// timeout occurred.
5391         /// </returns>
5392         /// <exception cref="T:System.ArgumentNullException">
5393         /// The <paramref name="tasks"/> argument is null.
5394         /// </exception>
5395         /// <exception cref="T:System.ArgumentException">
5396         /// The <paramref name="tasks"/> argument contains a null element.
5397         /// </exception>
5398         /// <exception cref="T:System.ArgumentOutOfRangeException">
5399         /// <paramref name="millisecondsTimeout"/> is a negative number other than -1, which represents an
5400         /// infinite time-out.
5401         /// </exception>
5402         [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
5403         public static int WaitAny(Task[] tasks, int millisecondsTimeout)
5404         {
5405             return WaitAny(tasks, millisecondsTimeout, default(CancellationToken));
5406         }
5407
5408         /// <summary>
5409         /// Waits for any of the provided <see cref="Task"/> objects to complete execution.
5410         /// </summary>
5411         /// <param name="tasks">
5412         /// An array of <see cref="Task"/> instances on which to wait.
5413         /// </param>
5414         /// <param name="millisecondsTimeout">
5415         /// The number of milliseconds to wait, or <see cref="System.Threading.Timeout.Infinite"/> (-1) to
5416         /// wait indefinitely.
5417         /// </param>
5418         /// <param name="cancellationToken">
5419         /// A <see cref="CancellationToken"/> to observe while waiting for a task to complete.
5420         /// </param>
5421         /// <returns>
5422         /// The index of the completed task in the <paramref name="tasks"/> array argument, or -1 if the
5423         /// timeout occurred.
5424         /// </returns>
5425         /// <exception cref="T:System.ArgumentNullException">
5426         /// The <paramref name="tasks"/> argument is null.
5427         /// </exception>
5428         /// <exception cref="T:System.ArgumentException">
5429         /// The <paramref name="tasks"/> argument contains a null element.
5430         /// </exception>
5431         /// <exception cref="T:System.ArgumentOutOfRangeException">
5432         /// <paramref name="millisecondsTimeout"/> is a negative number other than -1, which represents an
5433         /// infinite time-out.
5434         /// </exception>
5435         /// <exception cref="T:System.OperationCanceledException">
5436         /// The <paramref name="cancellationToken"/> was canceled.
5437         /// </exception>
5438         [MethodImpl(MethodImplOptions.NoOptimization)]  // this is needed for the parallel debugger
5439         public static int WaitAny(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
5440         {
5441             if (tasks == null)
5442             {
5443                 throw new ArgumentNullException("tasks");
5444             }
5445             if (millisecondsTimeout < -1)
5446             {
5447                 throw new ArgumentOutOfRangeException("millisecondsTimeout");
5448             }
5449             Contract.EndContractBlock();
5450
5451             cancellationToken.ThrowIfCancellationRequested(); // early check before we make any allocations
5452
5453             int signaledTaskIndex = -1;
5454
5455             // Make a pass through the loop to check for any tasks that may have
5456             // already been completed, and to verify that no tasks are null.
5457
5458             for (int taskIndex = 0; taskIndex < tasks.Length; taskIndex++)
5459             {
5460                 Task task = tasks[taskIndex];
5461
5462                 if (task == null)
5463                 {
5464                     throw new ArgumentException(Environment.GetResourceString("Task_WaitMulti_NullTask"), "tasks");
5465                 }
5466
5467                 if (signaledTaskIndex == -1 && task.IsCompleted)
5468                 {
5469                     // We found our first completed task.  Store it, but we can't just return here,
5470                     // as we still need to validate the whole array for nulls.
5471                     signaledTaskIndex = taskIndex;
5472                 }
5473             }
5474
5475             if (signaledTaskIndex == -1 && tasks.Length != 0)
5476             {
5477                 Task<Task> firstCompleted = TaskFactory.CommonCWAnyLogic(tasks);
5478                 bool waitCompleted = firstCompleted.Wait(millisecondsTimeout, cancellationToken);
5479                 if (waitCompleted)
5480                 {
5481                     Contract.Assert(firstCompleted.Status == TaskStatus.RanToCompletion);
5482                     signaledTaskIndex = Array.IndexOf(tasks, firstCompleted.Result);
5483                     Contract.Assert(signaledTaskIndex >= 0);
5484                 }
5485             }
5486
5487             // We need to prevent the tasks array from being GC'ed until we come out of the wait.
5488             // This is necessary so that the Parallel Debugger can traverse it during the long wait 
5489             // and deduce waiter/waitee relationships
5490             GC.KeepAlive(tasks);
5491
5492             // Return the index
5493             return signaledTaskIndex;
5494         }
5495
5496         #region FromResult / FromException / FromCancellation
5497
5498         /// <summary>Creates a <see cref="Task{TResult}"/> that's completed successfully with the specified result.</summary>
5499         /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
5500         /// <param name="result">The result to store into the completed task.</param>
5501         /// <returns>The successfully completed task.</returns>
5502         public static Task<TResult> FromResult<TResult>(TResult result)
5503         {
5504             return new Task<TResult>(result);
5505         }
5506
5507         /// <summary>Creates a <see cref="Task{TResult}"/> that's completed exceptionally with the specified exception.</summary>
5508         /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
5509         /// <param name="exception">The exception with which to complete the task.</param>
5510         /// <returns>The faulted task.</returns>
5511         public static Task FromException(Exception exception)
5512         {
5513             return FromException<VoidTaskResult>(exception);
5514         }
5515
5516         /// <summary>Creates a <see cref="Task{TResult}"/> that's completed exceptionally with the specified exception.</summary>
5517         /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
5518         /// <param name="exception">The exception with which to complete the task.</param>
5519         /// <returns>The faulted task.</returns>
5520         public static Task<TResult> FromException<TResult>(Exception exception)
5521         {
5522             if (exception == null) throw new ArgumentNullException("exception");
5523             Contract.EndContractBlock();
5524
5525             var task = new Task<TResult>();
5526             bool succeeded = task.TrySetException(exception);
5527             Contract.Assert(succeeded, "This should always succeed on a new task.");
5528             return task;
5529         }
5530
5531         /// <summary>Creates a <see cref="Task"/> that's completed due to cancellation with the specified token.</summary>
5532         /// <param name="cancellationToken">The token with which to complete the task.</param>
5533         /// <returns>The canceled task.</returns>
5534         [FriendAccessAllowed]
5535         internal static Task FromCancellation(CancellationToken cancellationToken)
5536         {
5537             if (!cancellationToken.IsCancellationRequested) throw new ArgumentOutOfRangeException("cancellationToken");
5538             Contract.EndContractBlock();
5539             return new Task(true, TaskCreationOptions.None, cancellationToken);
5540         }
5541         
5542         #if NET_4_6
5543         public static Task FromCanceled(CancellationToken cancellationToken)
5544         {
5545                 return FromCancellation(cancellationToken);
5546         }
5547         #endif
5548
5549         /// <summary>Creates a <see cref="Task"/> that's completed due to cancellation with the specified token.</summary>
5550         /// <param name="cancellationToken">The token with which to complete the task.</param>
5551         /// <returns>The canceled task.</returns>
5552         public static Task FromCanceled(CancellationToken cancellationToken)
5553         {
5554             return FromCancellation(cancellationToken);
5555         }
5556
5557         /// <summary>Creates a <see cref="Task{TResult}"/> that's completed due to cancellation with the specified token.</summary>
5558         /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
5559         /// <param name="cancellationToken">The token with which to complete the task.</param>
5560         /// <returns>The canceled task.</returns>
5561         [FriendAccessAllowed]
5562         internal static Task<TResult> FromCancellation<TResult>(CancellationToken cancellationToken)
5563         {
5564             if (!cancellationToken.IsCancellationRequested) throw new ArgumentOutOfRangeException("cancellationToken");
5565             Contract.EndContractBlock();
5566             return new Task<TResult>(true, default(TResult), TaskCreationOptions.None, cancellationToken);
5567         }
5568         
5569         #if NET_4_6
5570         public static Task<TResult> FromCanceled<TResult>(CancellationToken cancellationToken)
5571         {
5572                 return FromCancellation<TResult>(cancellationToken);
5573         }
5574         #endif
5575
5576         /// <summary>Creates a <see cref="Task{TResult}"/> that's completed due to cancellation with the specified token.</summary>
5577         /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
5578         /// <param name="cancellationToken">The token with which to complete the task.</param>
5579         /// <returns>The canceled task.</returns>
5580         public static Task<TResult> FromCanceled<TResult>(CancellationToken cancellationToken)
5581         {
5582             return FromCancellation<TResult>(cancellationToken);
5583         }
5584
5585         /// <summary>Creates a <see cref="Task{TResult}"/> that's completed due to cancellation with the specified exception.</summary>
5586         /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
5587         /// <param name="exception">The exception with which to complete the task.</param>
5588         /// <returns>The canceled task.</returns>
5589         internal static Task<TResult> FromCancellation<TResult>(OperationCanceledException exception)
5590         {
5591             if (exception == null) throw new ArgumentNullException("exception");
5592             Contract.EndContractBlock();
5593
5594             var task = new Task<TResult>();
5595             bool succeeded = task.TrySetCanceled(exception.CancellationToken, exception);
5596             Contract.Assert(succeeded, "This should always succeed on a new task.");
5597             return task;
5598         }
5599         #endregion
5600
5601         #region Run methods
5602
5603
5604         /// <summary>
5605         /// Queues the specified work to run on the ThreadPool and returns a Task handle for that work.
5606         /// </summary>
5607         /// <param name="action">The work to execute asynchronously</param>
5608         /// <returns>A Task that represents the work queued to execute in the ThreadPool.</returns>
5609         /// <exception cref="T:System.ArgumentNullException">
5610         /// The <paramref name="action"/> parameter was null.
5611         /// </exception>
5612         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
5613         public static Task Run(Action action)
5614         {
5615             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
5616             return Task.InternalStartNew(null, action, null, default(CancellationToken), TaskScheduler.Default,
5617                 TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, ref stackMark);
5618         }
5619
5620         /// <summary>
5621         /// Queues the specified work to run on the ThreadPool and returns a Task handle for that work.
5622         /// </summary>
5623         /// <param name="action">The work to execute asynchronously</param>
5624         /// <param name="cancellationToken">A cancellation token that should be used to cancel the work</param>
5625         /// <returns>A Task that represents the work queued to execute in the ThreadPool.</returns>
5626         /// <exception cref="T:System.ArgumentNullException">
5627         /// The <paramref name="action"/> parameter was null.
5628         /// </exception>
5629         /// <exception cref="T:System.ObjectDisposedException">
5630         /// The <see cref="T:System.CancellationTokenSource"/> associated with <paramref name="cancellationToken"/> was disposed.
5631         /// </exception>
5632         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
5633         public static Task Run(Action action, CancellationToken cancellationToken)
5634         {
5635             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
5636             return Task.InternalStartNew(null, action, null, cancellationToken, TaskScheduler.Default,
5637                 TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, ref stackMark);
5638         }
5639
5640         /// <summary>
5641         /// Queues the specified work to run on the ThreadPool and returns a Task(TResult) handle for that work.
5642         /// </summary>
5643         /// <param name="function">The work to execute asynchronously</param>
5644         /// <returns>A Task(TResult) that represents the work queued to execute in the ThreadPool.</returns>
5645         /// <exception cref="T:System.ArgumentNullException">
5646         /// The <paramref name="function"/> parameter was null.
5647         /// </exception>
5648         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
5649         public static Task<TResult> Run<TResult>(Func<TResult> function)
5650         {
5651             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
5652             return Task<TResult>.StartNew(null, function, default(CancellationToken),
5653                 TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, TaskScheduler.Default, ref stackMark);
5654         }
5655
5656         /// <summary>
5657         /// Queues the specified work to run on the ThreadPool and returns a Task(TResult) handle for that work.
5658         /// </summary>
5659         /// <param name="function">The work to execute asynchronously</param>
5660         /// <param name="cancellationToken">A cancellation token that should be used to cancel the work</param>
5661         /// <returns>A Task(TResult) that represents the work queued to execute in the ThreadPool.</returns>
5662         /// <exception cref="T:System.ArgumentNullException">
5663         /// The <paramref name="function"/> parameter was null.
5664         /// </exception>
5665         /// <exception cref="T:System.ObjectDisposedException">
5666         /// The <see cref="T:System.CancellationTokenSource"/> associated with <paramref name="cancellationToken"/> was disposed.
5667         /// </exception>
5668         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
5669         public static Task<TResult> Run<TResult>(Func<TResult> function, CancellationToken cancellationToken)
5670         {
5671             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
5672             return Task<TResult>.StartNew(null, function, cancellationToken,
5673                 TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, TaskScheduler.Default, ref stackMark);
5674         }
5675
5676         /// <summary>
5677         /// Queues the specified work to run on the ThreadPool and returns a proxy for the
5678         /// Task returned by <paramref name="function"/>.
5679         /// </summary>
5680         /// <param name="function">The work to execute asynchronously</param>
5681         /// <returns>A Task that represents a proxy for the Task returned by <paramref name="function"/>.</returns>
5682         /// <exception cref="T:System.ArgumentNullException">
5683         /// The <paramref name="function"/> parameter was null.
5684         /// </exception>
5685         public static Task Run(Func<Task> function)
5686         {
5687             return Run(function, default(CancellationToken));
5688         }
5689
5690
5691         /// <summary>
5692         /// Queues the specified work to run on the ThreadPool and returns a proxy for the
5693         /// Task returned by <paramref name="function"/>.
5694         /// </summary>
5695         /// <param name="function">The work to execute asynchronously</param>
5696         /// <param name="cancellationToken">A cancellation token that should be used to cancel the work</param>
5697         /// <returns>A Task that represents a proxy for the Task returned by <paramref name="function"/>.</returns>
5698         /// <exception cref="T:System.ArgumentNullException">
5699         /// The <paramref name="function"/> parameter was null.
5700         /// </exception>
5701         /// <exception cref="T:System.ObjectDisposedException">
5702         /// The <see cref="T:System.CancellationTokenSource"/> associated with <paramref name="cancellationToken"/> was disposed.
5703         /// </exception>
5704         public static Task Run(Func<Task> function, CancellationToken cancellationToken)
5705         {
5706             // Check arguments
5707             if (function == null) throw new ArgumentNullException("function");
5708             Contract.EndContractBlock();
5709
5710             if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
5711             {
5712                 cancellationToken.ThrowIfSourceDisposed();
5713             }
5714
5715             // Short-circuit if we are given a pre-canceled token
5716             if (cancellationToken.IsCancellationRequested)
5717                 return Task.FromCancellation(cancellationToken);
5718
5719             // Kick off initial Task, which will call the user-supplied function and yield a Task.
5720             Task<Task> task1 = Task<Task>.Factory.StartNew(function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
5721
5722             // Create a promise-style Task to be used as a proxy for the operation
5723             // Set lookForOce == true so that unwrap logic can be on the lookout for OCEs thrown as faults from task1, to support in-delegate cancellation.
5724             UnwrapPromise<VoidTaskResult> promise = new UnwrapPromise<VoidTaskResult>(task1, lookForOce: true);
5725
5726             return promise;
5727         }
5728
5729         /// <summary>
5730         /// Queues the specified work to run on the ThreadPool and returns a proxy for the
5731         /// Task(TResult) returned by <paramref name="function"/>.
5732         /// </summary>
5733         /// <typeparam name="TResult">The type of the result returned by the proxy Task.</typeparam>
5734         /// <param name="function">The work to execute asynchronously</param>
5735         /// <returns>A Task(TResult) that represents a proxy for the Task(TResult) returned by <paramref name="function"/>.</returns>
5736         /// <exception cref="T:System.ArgumentNullException">
5737         /// The <paramref name="function"/> parameter was null.
5738         /// </exception>
5739         public static Task<TResult> Run<TResult>(Func<Task<TResult>> function)
5740         {
5741             return Run(function, default(CancellationToken));
5742         }
5743
5744         /// <summary>
5745         /// Queues the specified work to run on the ThreadPool and returns a proxy for the
5746         /// Task(TResult) returned by <paramref name="function"/>.
5747         /// </summary>
5748         /// <typeparam name="TResult">The type of the result returned by the proxy Task.</typeparam>
5749         /// <param name="function">The work to execute asynchronously</param>
5750         /// <param name="cancellationToken">A cancellation token that should be used to cancel the work</param>
5751         /// <returns>A Task(TResult) that represents a proxy for the Task(TResult) returned by <paramref name="function"/>.</returns>
5752         /// <exception cref="T:System.ArgumentNullException">
5753         /// The <paramref name="function"/> parameter was null.
5754         /// </exception>
5755         public static Task<TResult> Run<TResult>(Func<Task<TResult>> function, CancellationToken cancellationToken)
5756         {
5757             // Check arguments
5758             if (function == null) throw new ArgumentNullException("function");
5759             Contract.EndContractBlock();
5760
5761             if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
5762             {
5763                 cancellationToken.ThrowIfSourceDisposed();
5764             }
5765
5766             // Short-circuit if we are given a pre-canceled token
5767             if (cancellationToken.IsCancellationRequested)
5768                 return Task.FromCancellation<TResult>(cancellationToken);
5769
5770             // Kick off initial Task, which will call the user-supplied function and yield a Task.
5771             Task<Task<TResult>> task1 = Task<Task<TResult>>.Factory.StartNew(function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
5772
5773             // Create a promise-style Task to be used as a proxy for the operation
5774             // Set lookForOce == true so that unwrap logic can be on the lookout for OCEs thrown as faults from task1, to support in-delegate cancellation.
5775             UnwrapPromise<TResult> promise = new UnwrapPromise<TResult>(task1, lookForOce: true);
5776
5777             return promise;
5778         }
5779
5780
5781         #endregion
5782
5783         #region Delay methods
5784
5785         /// <summary>
5786         /// Creates a Task that will complete after a time delay.
5787         /// </summary>
5788         /// <param name="delay">The time span to wait before completing the returned Task</param>
5789         /// <returns>A Task that represents the time delay</returns>
5790         /// <exception cref="T:System.ArgumentOutOfRangeException">
5791         /// The <paramref name="delay"/> is less than -1 or greater than Int32.MaxValue.
5792         /// </exception>
5793         /// <remarks>
5794         /// After the specified time delay, the Task is completed in RanToCompletion state.
5795         /// </remarks>
5796         public static Task Delay(TimeSpan delay)
5797         {
5798             return Delay(delay, default(CancellationToken));
5799         }
5800
5801         /// <summary>
5802         /// Creates a Task that will complete after a time delay.
5803         /// </summary>
5804         /// <param name="delay">The time span to wait before completing the returned Task</param>
5805         /// <param name="cancellationToken">The cancellation token that will be checked prior to completing the returned Task</param>
5806         /// <returns>A Task that represents the time delay</returns>
5807         /// <exception cref="T:System.ArgumentOutOfRangeException">
5808         /// The <paramref name="delay"/> is less than -1 or greater than Int32.MaxValue.
5809         /// </exception>
5810         /// <exception cref="T:System.ObjectDisposedException">
5811         /// The provided <paramref name="cancellationToken"/> has already been disposed.
5812         /// </exception>        
5813         /// <remarks>
5814         /// If the cancellation token is signaled before the specified time delay, then the Task is completed in
5815         /// Canceled state.  Otherwise, the Task is completed in RanToCompletion state once the specified time
5816         /// delay has expired.
5817         /// </remarks>        
5818         public static Task Delay(TimeSpan delay, CancellationToken cancellationToken)
5819         {
5820             long totalMilliseconds = (long)delay.TotalMilliseconds;
5821             if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
5822             {
5823                 throw new ArgumentOutOfRangeException("delay", Environment.GetResourceString("Task_Delay_InvalidDelay"));
5824             }
5825
5826             return Delay((int)totalMilliseconds, cancellationToken);
5827         }
5828
5829         /// <summary>
5830         /// Creates a Task that will complete after a time delay.
5831         /// </summary>
5832         /// <param name="millisecondsDelay">The number of milliseconds to wait before completing the returned Task</param>
5833         /// <returns>A Task that represents the time delay</returns>
5834         /// <exception cref="T:System.ArgumentOutOfRangeException">
5835         /// The <paramref name="millisecondsDelay"/> is less than -1.
5836         /// </exception>
5837         /// <remarks>
5838         /// After the specified time delay, the Task is completed in RanToCompletion state.
5839         /// </remarks>
5840         public static Task Delay(int millisecondsDelay)
5841         {
5842             return Delay(millisecondsDelay, default(CancellationToken));
5843         }
5844
5845         /// <summary>
5846         /// Creates a Task that will complete after a time delay.
5847         /// </summary>
5848         /// <param name="millisecondsDelay">The number of milliseconds to wait before completing the returned Task</param>
5849         /// <param name="cancellationToken">The cancellation token that will be checked prior to completing the returned Task</param>
5850         /// <returns>A Task that represents the time delay</returns>
5851         /// <exception cref="T:System.ArgumentOutOfRangeException">
5852         /// The <paramref name="millisecondsDelay"/> is less than -1.
5853         /// </exception>
5854         /// <exception cref="T:System.ObjectDisposedException">
5855         /// The provided <paramref name="cancellationToken"/> has already been disposed.
5856         /// </exception>        
5857         /// <remarks>
5858         /// If the cancellation token is signaled before the specified time delay, then the Task is completed in
5859         /// Canceled state.  Otherwise, the Task is completed in RanToCompletion state once the specified time
5860         /// delay has expired.
5861         /// </remarks>        
5862         public static Task Delay(int millisecondsDelay, CancellationToken cancellationToken)
5863         {
5864             // Throw on non-sensical time
5865             if (millisecondsDelay < -1)
5866             {
5867                 throw new ArgumentOutOfRangeException("millisecondsDelay", Environment.GetResourceString("Task_Delay_InvalidMillisecondsDelay"));
5868             }
5869             Contract.EndContractBlock();
5870
5871             // some short-cuts in case quick completion is in order
5872             if (cancellationToken.IsCancellationRequested)
5873             {
5874                 // return a Task created as already-Canceled
5875                 return Task.FromCancellation(cancellationToken);
5876             }
5877             else if (millisecondsDelay == 0)
5878             {
5879                 // return a Task created as already-RanToCompletion
5880                 return Task.CompletedTask;
5881             }
5882
5883             // Construct a promise-style Task to encapsulate our return value
5884             var promise = new DelayPromise(cancellationToken);
5885
5886             // Register our cancellation token, if necessary.
5887             if (cancellationToken.CanBeCanceled)
5888             {
5889                 promise.Registration = cancellationToken.InternalRegisterWithoutEC(state => ((DelayPromise)state).Complete(), promise);
5890             }
5891
5892             // ... and create our timer and make sure that it stays rooted.
5893             if (millisecondsDelay != Timeout.Infinite) // no need to create the timer if it's an infinite timeout
5894             {
5895                 promise.Timer = new Timer(state => ((DelayPromise)state).Complete(), promise, millisecondsDelay, Timeout.Infinite);
5896                 promise.Timer.KeepRootedWhileScheduled();
5897             }
5898
5899             // Return the timer proxy task
5900             return promise;
5901         }
5902
5903         /// <summary>Task that also stores the completion closure and logic for Task.Delay implementation.</summary>
5904         private sealed class DelayPromise : Task<VoidTaskResult>
5905         {
5906             internal DelayPromise(CancellationToken token)
5907                 : base()
5908             {
5909                 this.Token = token;
5910                 if (AsyncCausalityTracer.LoggingOn)
5911                     AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task.Delay", 0);
5912
5913                 if (Task.s_asyncDebuggingEnabled)
5914                 {
5915                     AddToActiveTasks(this);
5916                 }
5917             }
5918
5919             internal readonly CancellationToken Token;
5920             internal CancellationTokenRegistration Registration;
5921             internal Timer Timer;
5922
5923             internal void Complete()
5924             {
5925                 // Transition the task to completed.
5926                 bool setSucceeded;
5927
5928                 if (Token.IsCancellationRequested)
5929                 {
5930                     setSucceeded = TrySetCanceled(Token);
5931                 }
5932                 else
5933                 {
5934                     if (AsyncCausalityTracer.LoggingOn)
5935                         AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
5936
5937                     if (Task.s_asyncDebuggingEnabled)
5938                     {
5939                         RemoveFromActiveTasks(this.Id);
5940                     }
5941                     setSucceeded = TrySetResult(default(VoidTaskResult));
5942                 }
5943
5944                 // If we won the ----, also clean up.
5945                 if (setSucceeded)
5946                 {
5947                     if (Timer != null) Timer.Dispose();
5948                     Registration.Dispose();
5949                 }
5950             }
5951         }
5952         #endregion
5953
5954         #region WhenAll
5955         /// <summary>
5956         /// Creates a task that will complete when all of the supplied tasks have completed.
5957         /// </summary>
5958         /// <param name="tasks">The tasks to wait on for completion.</param>
5959         /// <returns>A task that represents the completion of all of the supplied tasks.</returns>
5960         /// <remarks>
5961         /// <para>
5962         /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state, 
5963         /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.  
5964         /// </para>
5965         /// <para>
5966         /// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
5967         /// </para>
5968         /// <para>
5969         /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.   
5970         /// </para>
5971         /// <para>
5972         /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion 
5973         /// state before it's returned to the caller.  
5974         /// </para>
5975         /// </remarks>
5976         /// <exception cref="T:System.ArgumentNullException">
5977         /// The <paramref name="tasks"/> argument was null.
5978         /// </exception>
5979         /// <exception cref="T:System.ArgumentException">
5980         /// The <paramref name="tasks"/> collection contained a null task.
5981         /// </exception>
5982         public static Task WhenAll(IEnumerable<Task> tasks)
5983         {
5984             // Take a more efficient path if tasks is actually an array
5985             Task[] taskArray = tasks as Task[];
5986             if (taskArray != null)
5987             {
5988                 return WhenAll(taskArray);
5989             }
5990
5991             // Skip a List allocation/copy if tasks is a collection
5992             ICollection<Task> taskCollection = tasks as ICollection<Task>;
5993             if (taskCollection != null)
5994             {
5995                 int index = 0;
5996                 taskArray = new Task[taskCollection.Count];
5997                 foreach (var task in tasks)
5998                 {
5999                     if (task == null) throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
6000                     taskArray[index++] = task;
6001                 }
6002                 return InternalWhenAll(taskArray);
6003             }
6004
6005             // Do some argument checking and convert tasks to a List (and later an array).
6006             if (tasks == null) throw new ArgumentNullException("tasks");
6007             List<Task> taskList = new List<Task>();
6008             foreach (Task task in tasks)
6009             {
6010                 if (task == null) throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
6011                 taskList.Add(task);
6012             }
6013
6014             // Delegate the rest to InternalWhenAll()
6015             return InternalWhenAll(taskList.ToArray());
6016         }
6017
6018         /// <summary>
6019         /// Creates a task that will complete when all of the supplied tasks have completed.
6020         /// </summary>
6021         /// <param name="tasks">The tasks to wait on for completion.</param>
6022         /// <returns>A task that represents the completion of all of the supplied tasks.</returns>
6023         /// <remarks>
6024         /// <para>
6025         /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state, 
6026         /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.  
6027         /// </para>
6028         /// <para>
6029         /// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
6030         /// </para>
6031         /// <para>
6032         /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.   
6033         /// </para>
6034         /// <para>
6035         /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion 
6036         /// state before it's returned to the caller.  
6037         /// </para>
6038         /// </remarks>
6039         /// <exception cref="T:System.ArgumentNullException">
6040         /// The <paramref name="tasks"/> argument was null.
6041         /// </exception>
6042         /// <exception cref="T:System.ArgumentException">
6043         /// The <paramref name="tasks"/> array contained a null task.
6044         /// </exception>
6045         public static Task WhenAll(params Task[] tasks)
6046         {
6047             // Do some argument checking and make a defensive copy of the tasks array
6048             if (tasks == null) throw new ArgumentNullException("tasks");
6049             Contract.EndContractBlock();
6050
6051             int taskCount = tasks.Length;
6052             if (taskCount == 0) return InternalWhenAll(tasks); // Small optimization in the case of an empty array.
6053
6054             Task[] tasksCopy = new Task[taskCount];
6055             for (int i = 0; i < taskCount; i++)
6056             {
6057                 Task task = tasks[i];
6058                 if (task == null) throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
6059                 tasksCopy[i] = task;
6060             }
6061
6062             // The rest can be delegated to InternalWhenAll()
6063             return InternalWhenAll(tasksCopy);
6064         }
6065
6066         // Some common logic to support WhenAll() methods
6067         // tasks should be a defensive copy.
6068         private static Task InternalWhenAll(Task[] tasks)
6069         {
6070             Contract.Requires(tasks != null, "Expected a non-null tasks array");
6071             return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait
6072                 Task.CompletedTask :
6073                 new WhenAllPromise(tasks);
6074         }
6075
6076         // A Task<VoidTaskResult> that gets completed when all of its constituent tasks complete.
6077         // Completion logic will analyze the antecedents in order to choose completion status.
6078         // This type allows us to replace this logic:
6079         //      Task<VoidTaskResult> promise = new Task<VoidTaskResult>(...);
6080         //      Action<Task> completionAction = delegate { <completion logic>};
6081         //      TaskFactory.CommonCWAllLogic(tasksCopy).AddCompletionAction(completionAction);
6082         //      return promise;
6083         // which involves several allocations, with this logic:
6084         //      return new WhenAllPromise(tasksCopy);
6085         // which saves a couple of allocations and enables debugger notification specialization.
6086         //
6087         // Used in InternalWhenAll(Task[])
6088         private sealed class WhenAllPromise : Task<VoidTaskResult>, ITaskCompletionAction
6089         {
6090             /// <summary>
6091             /// Stores all of the constituent tasks.  Tasks clear themselves out of this
6092             /// array as they complete, but only if they don't have their wait notification bit set.
6093             /// </summary>
6094             private readonly Task[] m_tasks;
6095             /// <summary>The number of tasks remaining to complete.</summary>
6096             private int m_count;
6097
6098             internal WhenAllPromise(Task[] tasks) :
6099                 base()
6100             {
6101                 Contract.Requires(tasks != null, "Expected a non-null task array");
6102                 Contract.Requires(tasks.Length > 0, "Expected a non-zero length task array");
6103
6104                 if (AsyncCausalityTracer.LoggingOn)
6105                     AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task.WhenAll", 0);
6106
6107                 if (s_asyncDebuggingEnabled)
6108                 {
6109                     AddToActiveTasks(this);
6110                 }
6111
6112                 m_tasks = tasks;
6113                 m_count = tasks.Length;
6114
6115                 foreach (var task in tasks)
6116                 {
6117                     if (task.IsCompleted) this.Invoke(task); // short-circuit the completion action, if possible
6118                     else task.AddCompletionAction(this); // simple completion action
6119                 }
6120             }
6121
6122             public void Invoke(Task completedTask)
6123             {
6124                 if (AsyncCausalityTracer.LoggingOn)
6125                     AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Join);
6126
6127                 // Decrement the count, and only continue to complete the promise if we're the last one.
6128                 if (Interlocked.Decrement(ref m_count) == 0)
6129                 {
6130                     // Set up some accounting variables
6131                     List<ExceptionDispatchInfo> observedExceptions = null;
6132                     Task canceledTask = null;
6133
6134                     // Loop through antecedents:
6135                     //   If any one of them faults, the result will be faulted
6136                     //   If none fault, but at least one is canceled, the result will be canceled
6137                     //   If none fault or are canceled, then result will be RanToCompletion
6138                     for (int i = 0; i < m_tasks.Length; i++)
6139                     {
6140                         var task = m_tasks[i];
6141                         Contract.Assert(task != null, "Constituent task in WhenAll should never be null");
6142
6143                         if (task.IsFaulted)
6144                         {
6145                             if (observedExceptions == null) observedExceptions = new List<ExceptionDispatchInfo>();
6146                             observedExceptions.AddRange(task.GetExceptionDispatchInfos());
6147                         }
6148                         else if (task.IsCanceled)
6149                         {
6150                             if (canceledTask == null) canceledTask = task; // use the first task that's canceled
6151                         }
6152
6153                         // Regardless of completion state, if the task has its debug bit set, transfer it to the
6154                         // WhenAll task.  We must do this before we complete the task.
6155                         if (task.IsWaitNotificationEnabled) this.SetNotificationForWaitCompletion(enabled: true);
6156                         else m_tasks[i] = null; // avoid holding onto tasks unnecessarily
6157                     }
6158
6159                     if (observedExceptions != null)
6160                     {
6161                         Contract.Assert(observedExceptions.Count > 0, "Expected at least one exception");
6162
6163                         //We don't need to TraceOperationCompleted here because TrySetException will call Finish and we'll log it there
6164
6165                         TrySetException(observedExceptions);
6166                     }
6167                     else if (canceledTask != null)
6168                     {
6169                         TrySetCanceled(canceledTask.CancellationToken, canceledTask.GetCancellationExceptionDispatchInfo());
6170                     }
6171                     else
6172                     {
6173                         if (AsyncCausalityTracer.LoggingOn)
6174                             AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
6175
6176                         if (Task.s_asyncDebuggingEnabled)
6177                         {
6178                             RemoveFromActiveTasks(this.Id);
6179                         }
6180                         TrySetResult(default(VoidTaskResult));
6181                     }
6182                 }
6183                 Contract.Assert(m_count >= 0, "Count should never go below 0");
6184             }
6185
6186             /// <summary>
6187             /// Returns whether we should notify the debugger of a wait completion.  This returns 
6188             /// true iff at least one constituent task has its bit set.
6189             /// </summary>
6190             internal override bool ShouldNotifyDebuggerOfWaitCompletion
6191             {
6192                 get
6193                 {
6194                     return
6195                         base.ShouldNotifyDebuggerOfWaitCompletion &&
6196                         Task.AnyTaskRequiresNotifyDebuggerOfWaitCompletion(m_tasks);
6197                 }
6198             }
6199         }
6200
6201         /// <summary>
6202         /// Creates a task that will complete when all of the supplied tasks have completed.
6203         /// </summary>
6204         /// <param name="tasks">The tasks to wait on for completion.</param>
6205         /// <returns>A task that represents the completion of all of the supplied tasks.</returns>
6206         /// <remarks>
6207         /// <para>
6208         /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state, 
6209         /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.  
6210         /// </para>
6211         /// <para>
6212         /// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
6213         /// </para>
6214         /// <para>
6215         /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.  
6216         /// The Result of the returned task will be set to an array containing all of the results of the 
6217         /// supplied tasks in the same order as they were provided (e.g. if the input tasks array contained t1, t2, t3, the output 
6218         /// task's Result will return an TResult[] where arr[0] == t1.Result, arr[1] == t2.Result, and arr[2] == t3.Result). 
6219         /// </para>
6220         /// <para>
6221         /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion 
6222         /// state before it's returned to the caller.  The returned TResult[] will be an array of 0 elements.
6223         /// </para>
6224         /// </remarks>
6225         /// <exception cref="T:System.ArgumentNullException">
6226         /// The <paramref name="tasks"/> argument was null.
6227         /// </exception>
6228         /// <exception cref="T:System.ArgumentException">
6229         /// The <paramref name="tasks"/> collection contained a null task.
6230         /// </exception>       
6231         public static Task<TResult[]> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks)
6232         {
6233             // Take a more efficient route if tasks is actually an array
6234             Task<TResult>[] taskArray = tasks as Task<TResult>[];
6235             if (taskArray != null)
6236             {
6237                 return WhenAll<TResult>(taskArray);
6238             }
6239
6240             // Skip a List allocation/copy if tasks is a collection
6241             ICollection<Task<TResult>> taskCollection = tasks as ICollection<Task<TResult>>;
6242             if (taskCollection != null)
6243             {
6244                 int index = 0;
6245                 taskArray = new Task<TResult>[taskCollection.Count];
6246                 foreach (var task in tasks)
6247                 {
6248                     if (task == null) throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
6249                     taskArray[index++] = task;
6250                 }
6251                 return InternalWhenAll<TResult>(taskArray);
6252             }
6253
6254             // Do some argument checking and convert tasks into a List (later an array)
6255             if (tasks == null) throw new ArgumentNullException("tasks");
6256             List<Task<TResult>> taskList = new List<Task<TResult>>();
6257             foreach (Task<TResult> task in tasks)
6258             {
6259                 if (task == null) throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
6260                 taskList.Add(task);
6261             }
6262
6263             // Delegate the rest to InternalWhenAll<TResult>().
6264             return InternalWhenAll<TResult>(taskList.ToArray());
6265         }
6266
6267         /// <summary>
6268         /// Creates a task that will complete when all of the supplied tasks have completed.
6269         /// </summary>
6270         /// <param name="tasks">The tasks to wait on for completion.</param>
6271         /// <returns>A task that represents the completion of all of the supplied tasks.</returns>
6272         /// <remarks>
6273         /// <para>
6274         /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state, 
6275         /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.  
6276         /// </para>
6277         /// <para>
6278         /// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
6279         /// </para>
6280         /// <para>
6281         /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.  
6282         /// The Result of the returned task will be set to an array containing all of the results of the 
6283         /// supplied tasks in the same order as they were provided (e.g. if the input tasks array contained t1, t2, t3, the output 
6284         /// task's Result will return an TResult[] where arr[0] == t1.Result, arr[1] == t2.Result, and arr[2] == t3.Result). 
6285         /// </para>
6286         /// <para>
6287         /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion 
6288         /// state before it's returned to the caller.  The returned TResult[] will be an array of 0 elements.
6289         /// </para>
6290         /// </remarks>
6291         /// <exception cref="T:System.ArgumentNullException">
6292         /// The <paramref name="tasks"/> argument was null.
6293         /// </exception>
6294         /// <exception cref="T:System.ArgumentException">
6295         /// The <paramref name="tasks"/> array contained a null task.
6296         /// </exception>
6297         public static Task<TResult[]> WhenAll<TResult>(params Task<TResult>[] tasks)
6298         {
6299             // Do some argument checking and make a defensive copy of the tasks array
6300             if (tasks == null) throw new ArgumentNullException("tasks");
6301             Contract.EndContractBlock();
6302
6303             int taskCount = tasks.Length;
6304             if (taskCount == 0) return InternalWhenAll<TResult>(tasks); // small optimization in the case of an empty task array
6305
6306             Task<TResult>[] tasksCopy = new Task<TResult>[taskCount];
6307             for (int i = 0; i < taskCount; i++)
6308             {
6309                 Task<TResult> task = tasks[i];
6310                 if (task == null) throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
6311                 tasksCopy[i] = task;
6312             }
6313
6314             // Delegate the rest to InternalWhenAll<TResult>()
6315             return InternalWhenAll<TResult>(tasksCopy);
6316         }
6317
6318         // Some common logic to support WhenAll<TResult> methods
6319         private static Task<TResult[]> InternalWhenAll<TResult>(Task<TResult>[] tasks)
6320         {
6321             Contract.Requires(tasks != null, "Expected a non-null tasks array");
6322             return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait
6323                 new Task<TResult[]>(false, new TResult[0], TaskCreationOptions.None, default(CancellationToken)) :
6324                 new WhenAllPromise<TResult>(tasks);
6325         }
6326
6327         // A Task<T> that gets completed when all of its constituent tasks complete.
6328         // Completion logic will analyze the antecedents in order to choose completion status.
6329         // See comments for non-generic version of WhenAllPromise class.
6330         //
6331         // Used in InternalWhenAll<TResult>(Task<TResult>[])
6332         private sealed class WhenAllPromise<T> : Task<T[]>, ITaskCompletionAction
6333         {
6334             /// <summary>
6335             /// Stores all of the constituent tasks.  Tasks clear themselves out of this
6336             /// array as they complete, but only if they don't have their wait notification bit set.
6337             /// </summary>
6338             private readonly Task<T>[] m_tasks;
6339             /// <summary>The number of tasks remaining to complete.</summary>
6340             private int m_count;
6341
6342             internal WhenAllPromise(Task<T>[] tasks) :
6343                 base()
6344             {
6345                 Contract.Requires(tasks != null, "Expected a non-null task array");
6346                 Contract.Requires(tasks.Length > 0, "Expected a non-zero length task array");
6347
6348                 m_tasks = tasks;
6349                 m_count = tasks.Length;
6350
6351                 if (AsyncCausalityTracer.LoggingOn)
6352                     AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task.WhenAll", 0);
6353
6354                 if (s_asyncDebuggingEnabled)
6355                 {
6356                     AddToActiveTasks(this);
6357                 }
6358
6359                 foreach (var task in tasks)
6360                 {
6361                     if (task.IsCompleted) this.Invoke(task); // short-circuit the completion action, if possible
6362                     else task.AddCompletionAction(this); // simple completion action
6363                 }
6364             }
6365
6366             public void Invoke(Task ignored)
6367             {
6368                 if (AsyncCausalityTracer.LoggingOn)
6369                     AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Join);
6370
6371                 // Decrement the count, and only continue to complete the promise if we're the last one.
6372                 if (Interlocked.Decrement(ref m_count) == 0)
6373                 {
6374                     // Set up some accounting variables
6375                     T[] results = new T[m_tasks.Length];
6376                     List<ExceptionDispatchInfo> observedExceptions = null;
6377                     Task canceledTask = null;
6378
6379                     // Loop through antecedents:
6380                     //   If any one of them faults, the result will be faulted
6381                     //   If none fault, but at least one is canceled, the result will be canceled
6382                     //   If none fault or are canceled, then result will be RanToCompletion
6383                     for (int i = 0; i < m_tasks.Length; i++)
6384                     {
6385                         Task<T> task = m_tasks[i];
6386                         Contract.Assert(task != null, "Constituent task in WhenAll should never be null");
6387
6388                         if (task.IsFaulted)
6389                         {
6390                             if (observedExceptions == null) observedExceptions = new List<ExceptionDispatchInfo>();
6391                             observedExceptions.AddRange(task.GetExceptionDispatchInfos());
6392                         }
6393                         else if (task.IsCanceled)
6394                         {
6395                             if (canceledTask == null) canceledTask = task; // use the first task that's canceled
6396                         }
6397                         else
6398                         {
6399                             Contract.Assert(task.Status == TaskStatus.RanToCompletion);
6400                             results[i] = task.GetResultCore(waitCompletionNotification: false); // avoid Result, which would triggering debug notification
6401                         }
6402
6403                         // Regardless of completion state, if the task has its debug bit set, transfer it to the
6404                         // WhenAll task.  We must do this before we complete the task.
6405                         if (task.IsWaitNotificationEnabled) this.SetNotificationForWaitCompletion(enabled: true);
6406                         else m_tasks[i] = null; // avoid holding onto tasks unnecessarily
6407                     }
6408
6409                     if (observedExceptions != null)
6410                     {
6411                         Contract.Assert(observedExceptions.Count > 0, "Expected at least one exception");
6412
6413                         //We don't need to TraceOperationCompleted here because TrySetException will call Finish and we'll log it there
6414
6415                         TrySetException(observedExceptions);
6416                     }
6417                     else if (canceledTask != null)
6418                     {
6419                         TrySetCanceled(canceledTask.CancellationToken, canceledTask.GetCancellationExceptionDispatchInfo());
6420                     }
6421                     else
6422                     {
6423                         if (AsyncCausalityTracer.LoggingOn)
6424                             AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
6425
6426                         if (Task.s_asyncDebuggingEnabled)
6427                         {
6428                             RemoveFromActiveTasks(this.Id);
6429                         }
6430                         TrySetResult(results);
6431                     }
6432                 }
6433                 Contract.Assert(m_count >= 0, "Count should never go below 0");
6434             }
6435
6436             /// <summary>
6437             /// Returns whether we should notify the debugger of a wait completion.  This returns true
6438             /// iff at least one constituent task has its bit set.
6439             /// </summary>
6440             internal override bool ShouldNotifyDebuggerOfWaitCompletion
6441             {
6442                 get
6443                 {
6444                     return
6445                         base.ShouldNotifyDebuggerOfWaitCompletion &&
6446                         Task.AnyTaskRequiresNotifyDebuggerOfWaitCompletion(m_tasks);
6447                 }
6448             }
6449         }
6450         #endregion
6451
6452         #region WhenAny
6453         /// <summary>
6454         /// Creates a task that will complete when any of the supplied tasks have completed.
6455         /// </summary>
6456         /// <param name="tasks">The tasks to wait on for completion.</param>
6457         /// <returns>A task that represents the completion of one of the supplied tasks.  The return Task's Result is the task that completed.</returns>
6458         /// <remarks>
6459         /// The returned task will complete when any of the supplied tasks has completed.  The returned task will always end in the RanToCompletion state 
6460         /// with its Result set to the first task to complete.  This is true even if the first task to complete ended in the Canceled or Faulted state.
6461         /// </remarks>
6462         /// <exception cref="T:System.ArgumentNullException">
6463         /// The <paramref name="tasks"/> argument was null.
6464         /// </exception>
6465         /// <exception cref="T:System.ArgumentException">
6466         /// The <paramref name="tasks"/> array contained a null task, or was empty.
6467         /// </exception>
6468         public static Task<Task> WhenAny(params Task[] tasks)
6469         {
6470             if (tasks == null) throw new ArgumentNullException("tasks");
6471             if (tasks.Length == 0)
6472             {
6473                 throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), "tasks");
6474             }
6475             Contract.EndContractBlock();
6476
6477             // Make a defensive copy, as the user may manipulate the tasks array
6478             // after we return but before the WhenAny asynchronously completes.
6479             int taskCount = tasks.Length;
6480             Task[] tasksCopy = new Task[taskCount];
6481             for (int i = 0; i < taskCount; i++)
6482             {
6483                 Task task = tasks[i];
6484                 if (task == null) throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
6485                 tasksCopy[i] = task;
6486             }
6487
6488             // Previously implemented CommonCWAnyLogic() can handle the rest
6489             return TaskFactory.CommonCWAnyLogic(tasksCopy);
6490         }
6491
6492         /// <summary>
6493         /// Creates a task that will complete when any of the supplied tasks have completed.
6494         /// </summary>
6495         /// <param name="tasks">The tasks to wait on for completion.</param>
6496         /// <returns>A task that represents the completion of one of the supplied tasks.  The return Task's Result is the task that completed.</returns>
6497         /// <remarks>
6498         /// The returned task will complete when any of the supplied tasks has completed.  The returned task will always end in the RanToCompletion state 
6499         /// with its Result set to the first task to complete.  This is true even if the first task to complete ended in the Canceled or Faulted state.
6500         /// </remarks>
6501         /// <exception cref="T:System.ArgumentNullException">
6502         /// The <paramref name="tasks"/> argument was null.
6503         /// </exception>
6504         /// <exception cref="T:System.ArgumentException">
6505         /// The <paramref name="tasks"/> collection contained a null task, or was empty.
6506         /// </exception>
6507         public static Task<Task> WhenAny(IEnumerable<Task> tasks)
6508         {
6509             if (tasks == null) throw new ArgumentNullException("tasks");
6510             Contract.EndContractBlock();
6511
6512             // Make a defensive copy, as the user may manipulate the tasks collection
6513             // after we return but before the WhenAny asynchronously completes.
6514             List<Task> taskList = new List<Task>();
6515             foreach (Task task in tasks)
6516             {
6517                 if (task == null) throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
6518                 taskList.Add(task);
6519             }
6520
6521             if (taskList.Count == 0)
6522             {
6523                 throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), "tasks");
6524             }
6525
6526             // Previously implemented CommonCWAnyLogic() can handle the rest
6527             return TaskFactory.CommonCWAnyLogic(taskList);
6528         }
6529
6530         /// <summary>
6531         /// Creates a task that will complete when any of the supplied tasks have completed.
6532         /// </summary>
6533         /// <param name="tasks">The tasks to wait on for completion.</param>
6534         /// <returns>A task that represents the completion of one of the supplied tasks.  The return Task's Result is the task that completed.</returns>
6535         /// <remarks>
6536         /// The returned task will complete when any of the supplied tasks has completed.  The returned task will always end in the RanToCompletion state 
6537         /// with its Result set to the first task to complete.  This is true even if the first task to complete ended in the Canceled or Faulted state.
6538         /// </remarks>
6539         /// <exception cref="T:System.ArgumentNullException">
6540         /// The <paramref name="tasks"/> argument was null.
6541         /// </exception>
6542         /// <exception cref="T:System.ArgumentException">
6543         /// The <paramref name="tasks"/> array contained a null task, or was empty.
6544         /// </exception>
6545         public static Task<Task<TResult>> WhenAny<TResult>(params Task<TResult>[] tasks)
6546         {
6547             // We would just like to do this:
6548             //    return (Task<Task<TResult>>) WhenAny( (Task[]) tasks);
6549             // but classes are not covariant to enable casting Task<TResult> to Task<Task<TResult>>.
6550
6551             // Call WhenAny(Task[]) for basic functionality
6552             Task<Task> intermediate = WhenAny((Task[])tasks);
6553
6554             // Return a continuation task with the correct result type
6555             return intermediate.ContinueWith(Task<TResult>.TaskWhenAnyCast, default(CancellationToken),
6556                 TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default);
6557         }
6558
6559         /// <summary>
6560         /// Creates a task that will complete when any of the supplied tasks have completed.
6561         /// </summary>
6562         /// <param name="tasks">The tasks to wait on for completion.</param>
6563         /// <returns>A task that represents the completion of one of the supplied tasks.  The return Task's Result is the task that completed.</returns>
6564         /// <remarks>
6565         /// The returned task will complete when any of the supplied tasks has completed.  The returned task will always end in the RanToCompletion state 
6566         /// with its Result set to the first task to complete.  This is true even if the first task to complete ended in the Canceled or Faulted state.
6567         /// </remarks>
6568         /// <exception cref="T:System.ArgumentNullException">
6569         /// The <paramref name="tasks"/> argument was null.
6570         /// </exception>
6571         /// <exception cref="T:System.ArgumentException">
6572         /// The <paramref name="tasks"/> collection contained a null task, or was empty.
6573         /// </exception>
6574         public static Task<Task<TResult>> WhenAny<TResult>(IEnumerable<Task<TResult>> tasks)
6575         {
6576             // We would just like to do this:
6577             //    return (Task<Task<TResult>>) WhenAny( (IEnumerable<Task>) tasks);
6578             // but classes are not covariant to enable casting Task<TResult> to Task<Task<TResult>>.
6579
6580             // Call WhenAny(IEnumerable<Task>) for basic functionality
6581             Task<Task> intermediate = WhenAny((IEnumerable<Task>)tasks);
6582
6583             // Return a continuation task with the correct result type
6584             return intermediate.ContinueWith(Task<TResult>.TaskWhenAnyCast, default(CancellationToken),
6585                 TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default);
6586         }
6587         #endregion
6588
6589         [FriendAccessAllowed]
6590         internal static Task<TResult> CreateUnwrapPromise<TResult>(Task outerTask, bool lookForOce)
6591         {
6592             Contract.Requires(outerTask != null);
6593
6594             return new UnwrapPromise<TResult>(outerTask, lookForOce);
6595         }
6596
6597         internal virtual Delegate[] GetDelegateContinuationsForDebugger()
6598         {
6599             //Avoid an infinite loop by making sure the continuation object is not a reference to istelf.
6600             if (this.m_continuationObject != this)
6601                 return GetDelegatesFromContinuationObject(this.m_continuationObject);
6602             else
6603                 return null;
6604         }
6605
6606         internal static Delegate[] GetDelegatesFromContinuationObject(object continuationObject)
6607         {
6608             if (continuationObject != null)
6609             {
6610                 Action singleAction = continuationObject as Action;
6611                 if (singleAction != null)
6612                 {
6613                     return new Delegate[] { AsyncMethodBuilderCore.TryGetStateMachineForDebugger(singleAction) };
6614                 }
6615
6616                 TaskContinuation taskContinuation = continuationObject as TaskContinuation;
6617                 if (taskContinuation != null)
6618                 {
6619                     return taskContinuation.GetDelegateContinuationsForDebugger();
6620                 }
6621
6622                 Task continuationTask = continuationObject as Task;
6623                 if (continuationTask != null)
6624                 {
6625                     Contract.Assert(continuationTask.m_action == null);
6626                     Delegate[] delegates = continuationTask.GetDelegateContinuationsForDebugger();
6627                     if (delegates != null)
6628                         return delegates;
6629                 }
6630
6631                 //We need this ITaskCompletionAction after the Task because in the case of UnwrapPromise
6632                 //the VS debugger is more interested in the continuation than the internal invoke()
6633                 ITaskCompletionAction singleCompletionAction = continuationObject as ITaskCompletionAction;
6634                 if (singleCompletionAction != null)
6635                 {
6636                     return new Delegate[] { new Action<Task>(singleCompletionAction.Invoke) };
6637                 }
6638
6639                 List<object> continuationList = continuationObject as List<object>;
6640                 if (continuationList != null)
6641                 {
6642                     List<Delegate> result = new List<Delegate>();
6643                     foreach (object obj in continuationList)
6644                     {
6645                         var innerDelegates = GetDelegatesFromContinuationObject(obj);
6646                         if (innerDelegates != null)
6647                         {
6648                             foreach (var del in innerDelegates)
6649                             {
6650                                 if (del != null)
6651                                     result.Add(del);
6652                             }
6653                         }
6654                     }
6655
6656                     return result.ToArray();
6657                 }
6658             }
6659
6660             return null;
6661         }
6662
6663         private static Task GetActiveTaskFromId(int taskId)
6664         {
6665             Task task = null;
6666             s_currentActiveTasks.TryGetValue(taskId, out task);
6667             return task;
6668         }
6669
6670         private static Task[] GetActiveTasks()
6671         {
6672             
6673             return new List<Task>(s_currentActiveTasks.Values).ToArray();
6674         }
6675     }
6676
6677     // Proxy class for better debugging experience
6678     internal class SystemThreadingTasks_TaskDebugView
6679     {
6680         private Task m_task;
6681
6682         public SystemThreadingTasks_TaskDebugView(Task task)
6683         {
6684             m_task = task;
6685         }
6686
6687         public object AsyncState { get { return m_task.AsyncState; } }
6688         public TaskCreationOptions CreationOptions { get { return m_task.CreationOptions; } }
6689         public Exception Exception { get { return m_task.Exception; } }
6690         public int Id { get { return m_task.Id; } }
6691         public bool CancellationPending { get { return (m_task.Status == TaskStatus.WaitingToRun) && m_task.CancellationToken.IsCancellationRequested; } }
6692         public TaskStatus Status { get { return m_task.Status; } }
6693     }
6694
6695     // Special purpose derivation of Task that supports limited replication through
6696     // overriding the ShouldReplicate() method.  This is used by the Parallel.For/ForEach
6697     // methods.
6698     internal class ParallelForReplicatingTask : Task
6699     {
6700         // Member variables
6701         private int m_replicationDownCount; // downcounter to control replication
6702
6703         //
6704         // Constructors
6705         //
6706
6707         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
6708         internal ParallelForReplicatingTask(
6709             ParallelOptions parallelOptions, Action action, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions)
6710             : base(action, null, Task.InternalCurrent, default(CancellationToken), creationOptions, internalOptions | InternalTaskOptions.SelfReplicating, null)
6711         {
6712             // Compute the down count based on scheduler/DOP info in parallelOptions.
6713             m_replicationDownCount = parallelOptions.EffectiveMaxConcurrencyLevel;
6714
6715             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
6716             PossiblyCaptureContext(ref stackMark);
6717         }
6718
6719
6720         // Controls degree of replication.  If downcounter is initialized to -1, then
6721         // replication will be allowed to "run wild".  Otherwise, this method decrements
6722         // the downcounter each time it is called, calling false when it is called with
6723         // a zero downcounter.  This method returning false effectively ends the replication
6724         // of the associated ParallelForReplicatingTask.
6725         internal override bool ShouldReplicate()
6726         {
6727             if (m_replicationDownCount == -1) return true; // "run wild"
6728
6729             if (m_replicationDownCount > 0) // Decrement and return true if not called with 0 downcount
6730             {
6731                 m_replicationDownCount--;
6732                 return true;
6733             }
6734
6735             return false; // We're done replicating
6736         }
6737
6738         internal override Task CreateReplicaTask(Action<object> taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
6739                                             TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica)
6740         {
6741             return new ParallelForReplicaTask(taskReplicaDelegate, stateObject, parentTask, taskScheduler,
6742                                             creationOptionsForReplica, internalOptionsForReplica);
6743         }
6744
6745
6746     }
6747
6748     internal class ParallelForReplicaTask : Task
6749     {
6750         internal object m_stateForNextReplica;  // some replicas may quit prematurely, in which case they will use this variable
6751         // to save state they want to be picked up by the next replica queued to the same thread
6752
6753         internal object m_stateFromPreviousReplica;  // some replicas may quit prematurely, in which case they will use this variable
6754         // to save state they want to be picked up by the next replica queued to the same thread
6755
6756         internal Task m_handedOverChildReplica;  // some replicas may quit prematurely, in which case they will use this variable
6757         // to hand over the child replica they had queued to the next task that will replace them
6758
6759         internal ParallelForReplicaTask(Action<object> taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
6760                                        TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica) :
6761             base(taskReplicaDelegate, stateObject, parentTask, default(CancellationToken), creationOptionsForReplica, internalOptionsForReplica, taskScheduler)
6762         {
6763         }
6764
6765         // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
6766         internal override Object SavedStateForNextReplica
6767         {
6768             get { return m_stateForNextReplica; }
6769
6770             set { m_stateForNextReplica = value; }
6771         }
6772
6773         // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
6774         internal override Object SavedStateFromPreviousReplica
6775         {
6776             get { return m_stateFromPreviousReplica; }
6777
6778             set { m_stateFromPreviousReplica = value; }
6779         }
6780
6781         // Allows internal deriving classes to support replicas that exit prematurely and want to hand over the child replica that they
6782         // had queued, so that the replacement replica can work with that child task instead of queuing up yet another one
6783         internal override Task HandedOverChildReplica
6784         {
6785             get { return m_handedOverChildReplica; }
6786
6787             set { m_handedOverChildReplica = value; }
6788         }
6789     }
6790
6791     /// <summary>
6792     /// Specifies flags that control optional behavior for the creation and execution of tasks.
6793     /// </summary>
6794     // NOTE: These options are a subset of TaskContinuationsOptions, thus before adding a flag check it is
6795     // not already in use.
6796     [Flags]
6797     [Serializable]
6798     public enum TaskCreationOptions
6799     {
6800         /// <summary>
6801         /// Specifies that the default behavior should be used.
6802         /// </summary>
6803         None = 0x0,
6804
6805         /// <summary>
6806         /// A hint to a <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> to schedule a
6807         /// task in as fair a manner as possible, meaning that tasks scheduled sooner will be more likely to
6808         /// be run sooner, and tasks scheduled later will be more likely to be run later.
6809         /// </summary>
6810         PreferFairness = 0x01,
6811
6812         /// <summary>
6813         /// Specifies that a task will be a long-running, course-grained operation. It provides a hint to the
6814         /// <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> that oversubscription may be
6815         /// warranted. 
6816         /// </summary>
6817         LongRunning = 0x02,
6818
6819         /// <summary>
6820         /// Specifies that a task is attached to a parent in the task hierarchy.
6821         /// </summary>
6822         AttachedToParent = 0x04,
6823
6824         /// <summary>
6825         /// Specifies that an InvalidOperationException will be thrown if an attempt is made to attach a child task to the created task.
6826         /// </summary>
6827         DenyChildAttach = 0x08,
6828
6829         /// <summary>
6830         /// Prevents the ambient scheduler from being seen as the current scheduler in the created task.  This means that operations
6831         /// like StartNew or ContinueWith that are performed in the created task will see TaskScheduler.Default as the current scheduler.
6832         /// </summary>
6833         HideScheduler = 0x10,
6834
6835         // 0x20 is already being used in TaskContinuationOptions
6836
6837         /// <summary>
6838         /// Forces continuations added to the current task to be executed asynchronously.
6839         /// This option has precedence over TaskContinuationOptions.ExecuteSynchronously
6840         /// </summary>
6841         RunContinuationsAsynchronously = 0x40
6842     }
6843
6844
6845     /// <summary>
6846     /// Task creation flags which are only used internally.
6847     /// </summary>
6848     [Flags]
6849     [Serializable]
6850     internal enum InternalTaskOptions
6851     {
6852         /// <summary> Specifies "No internal task options" </summary>
6853         None,
6854
6855         /// <summary>Used to filter out internal vs. public task creation options.</summary>
6856         InternalOptionsMask = 0x0000FF00,
6857
6858         ChildReplica = 0x0100,
6859         ContinuationTask = 0x0200,
6860         PromiseTask = 0x0400,
6861         SelfReplicating = 0x0800,
6862
6863         /// <summary>
6864         /// Store the presence of TaskContinuationOptions.LazyCancellation, since it does not directly
6865         /// translate into any TaskCreationOptions.
6866         /// </summary>
6867         LazyCancellation = 0x1000,
6868
6869         /// <summary>Specifies that the task will be queued by the runtime before handing it over to the user. 
6870         /// This flag will be used to skip the cancellationtoken registration step, which is only meant for unstarted tasks.</summary>
6871         QueuedByRuntime = 0x2000,
6872
6873         /// <summary>
6874         /// Denotes that Dispose should be a complete nop for a Task.  Used when constructing tasks that are meant to be cached/reused.
6875         /// </summary>
6876         DoNotDispose = 0x4000
6877     }
6878
6879     /// <summary>
6880     /// Specifies flags that control optional behavior for the creation and execution of continuation tasks.
6881     /// </summary>
6882     [Flags]
6883     [Serializable]
6884     public enum TaskContinuationOptions
6885     {
6886         /// <summary>
6887         /// Default = "Continue on any, no task options, run asynchronously"
6888         /// Specifies that the default behavior should be used.  Continuations, by default, will
6889         /// be scheduled when the antecedent task completes, regardless of the task's final <see
6890         /// cref="System.Threading.Tasks.TaskStatus">TaskStatus</see>.
6891         /// </summary>
6892         None = 0,
6893
6894         // These are identical to their meanings and values in TaskCreationOptions
6895
6896         /// <summary>
6897         /// A hint to a <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> to schedule a
6898         /// task in as fair a manner as possible, meaning that tasks scheduled sooner will be more likely to
6899         /// be run sooner, and tasks scheduled later will be more likely to be run later.
6900         /// </summary>
6901         PreferFairness = 0x01,
6902
6903         /// <summary>
6904         /// Specifies that a task will be a long-running, course-grained operation.  It provides
6905         /// a hint to the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> that
6906         /// oversubscription may be warranted.
6907         /// </summary>
6908         LongRunning = 0x02,
6909         /// <summary>
6910         /// Specifies that a task is attached to a parent in the task hierarchy.
6911         /// </summary>
6912         AttachedToParent = 0x04,
6913
6914         /// <summary>
6915         /// Specifies that an InvalidOperationException will be thrown if an attempt is made to attach a child task to the created task.
6916         /// </summary>
6917         DenyChildAttach = 0x08,
6918         /// <summary>
6919         /// Prevents the ambient scheduler from being seen as the current scheduler in the created task.  This means that operations
6920         /// like StartNew or ContinueWith that are performed in the created task will see TaskScheduler.Default as the current scheduler.
6921         /// </summary>
6922         HideScheduler = 0x10,
6923
6924         /// <summary>
6925         /// In the case of continuation cancellation, prevents completion of the continuation until the antecedent has completed.
6926         /// </summary>
6927         LazyCancellation = 0x20,
6928
6929         RunContinuationsAsynchronously = 0x40,
6930
6931         // These are specific to continuations
6932
6933         /// <summary>
6934         /// Specifies that the continuation task should not be scheduled if its antecedent ran to completion.
6935         /// This option is not valid for multi-task continuations.
6936         /// </summary>
6937         NotOnRanToCompletion = 0x10000,
6938         /// <summary>
6939         /// Specifies that the continuation task should not be scheduled if its antecedent threw an unhandled
6940         /// exception. This option is not valid for multi-task continuations.
6941         /// </summary>
6942         NotOnFaulted = 0x20000,
6943         /// <summary>
6944         /// Specifies that the continuation task should not be scheduled if its antecedent was canceled. This
6945         /// option is not valid for multi-task continuations.
6946         /// </summary>
6947         NotOnCanceled = 0x40000,
6948         /// <summary>
6949         /// Specifies that the continuation task should be scheduled only if its antecedent ran to
6950         /// completion. This option is not valid for multi-task continuations.
6951         /// </summary>
6952         OnlyOnRanToCompletion = NotOnFaulted | NotOnCanceled,
6953         /// <summary>
6954         /// Specifies that the continuation task should be scheduled only if its antecedent threw an
6955         /// unhandled exception. This option is not valid for multi-task continuations.
6956         /// </summary>
6957         OnlyOnFaulted = NotOnRanToCompletion | NotOnCanceled,
6958         /// <summary>
6959         /// Specifies that the continuation task should be scheduled only if its antecedent was canceled.
6960         /// This option is not valid for multi-task continuations.
6961         /// </summary>
6962         OnlyOnCanceled = NotOnRanToCompletion | NotOnFaulted,
6963         /// <summary>
6964         /// Specifies that the continuation task should be executed synchronously. With this option
6965         /// specified, the continuation will be run on the same thread that causes the antecedent task to
6966         /// transition into its final state. If the antecedent is already complete when the continuation is
6967         /// created, the continuation will run on the thread creating the continuation.  Only very
6968         /// short-running continuations should be executed synchronously.
6969         /// </summary>
6970         ExecuteSynchronously = 0x80000
6971     }
6972
6973     /// <summary>
6974     /// Internal helper class to keep track of stack depth and decide whether we should inline or not.
6975     /// </summary>
6976     internal class StackGuard
6977     {
6978         // current thread's depth of nested inline task executions
6979         private int m_inliningDepth = 0;
6980
6981         // For relatively small inlining depths we don't want to get into the business of stack probing etc.
6982         // This clearly leaves a window of opportunity for the user code to SO. However a piece of code
6983         // that can SO in 20 inlines on a typical 1MB stack size probably needs to be revisited anyway.
6984         private const int MAX_UNCHECKED_INLINING_DEPTH = 20;
6985
6986 #if !FEATURE_PAL && !PFX_LEGACY_3_5
6987
6988         private UInt64 m_lastKnownWatermark;
6989         private static int s_pageSize;
6990
6991         // We are conservative here. We assume that the platform needs a whole 64KB to
6992         // respond to stack overflow. This means that for very small stacks (e.g. 128KB) 
6993         // we'll fail a lot of stack checks incorrectly.
6994         private const long STACK_RESERVED_SPACE = 4096 * 16;
6995
6996 #endif  // !FEATURE_PAL && !PFX_LEGACY_3_5
6997
6998         /// <summary>
6999         /// This method needs to be called before attempting inline execution on the current thread. 
7000         /// If false is returned, it means we are too close to the end of the stack and should give up inlining.
7001         /// Each call to TryBeginInliningScope() that returns true must be matched with a 
7002         /// call to EndInliningScope() regardless of whether inlining actually took place.
7003         /// </summary>
7004         [SecuritySafeCritical]
7005         internal bool TryBeginInliningScope()
7006         {
7007             // If we're still under the 'safe' limit we'll just skip the stack probe to save p/invoke calls
7008             if (m_inliningDepth < MAX_UNCHECKED_INLINING_DEPTH || CheckForSufficientStack())
7009             {
7010                 m_inliningDepth++;
7011                 return true;
7012             }
7013             else
7014                 return false;
7015         }
7016
7017         /// <summary>
7018         /// This needs to be called once for each previous successful TryBeginInliningScope() call after
7019         /// inlining related logic runs.
7020         /// </summary>
7021         internal void EndInliningScope()
7022         {
7023             m_inliningDepth--;
7024             Contract.Assert(m_inliningDepth >= 0, "Inlining depth count should never go negative.");
7025
7026             // do the right thing just in case...
7027             if (m_inliningDepth < 0) m_inliningDepth = 0;
7028         }
7029
7030         [SecurityCritical]
7031         private unsafe bool CheckForSufficientStack()
7032         {
7033 #if !FEATURE_PAL && !PFX_LEGACY_3_5
7034             // see if we already have the system page size info recorded
7035             int pageSize = s_pageSize;
7036             if (pageSize == 0)
7037             {
7038                 // If not we need to query it from GetSystemInfo()
7039                 // Note that this happens only once for the process lifetime
7040                 Win32Native.SYSTEM_INFO sysInfo = new Win32Native.SYSTEM_INFO();
7041                 Win32Native.GetSystemInfo(ref sysInfo);
7042
7043                 s_pageSize = pageSize = sysInfo.dwPageSize;
7044             }
7045
7046             Win32Native.MEMORY_BASIC_INFORMATION stackInfo = new Win32Native.MEMORY_BASIC_INFORMATION();
7047
7048             // We subtract one page for our request. VirtualQuery rounds UP to the next page.
7049             // Unfortunately, the stack grows down. If we're on the first page (last page in the
7050             // VirtualAlloc), we'll be moved to the next page, which is off the stack! 
7051
7052             UIntPtr currentAddr = new UIntPtr(&stackInfo - pageSize);
7053             UInt64 current64 = currentAddr.ToUInt64();
7054
7055             // Check whether we previously recorded a deeper stack than where we currently are,
7056             // If so we don't need to do the P/Invoke to VirtualQuery
7057             if (m_lastKnownWatermark != 0 && current64 > m_lastKnownWatermark)
7058                 return true;
7059
7060             // Actual stack probe. P/Invoke to query for the current stack allocation information.            
7061             Win32Native.VirtualQuery(currentAddr.ToPointer(), ref stackInfo, (UIntPtr)(sizeof(Win32Native.MEMORY_BASIC_INFORMATION)));
7062
7063             // If the current address minus the base (remember: the stack grows downward in the
7064             // address space) is greater than the number of bytes requested plus the reserved
7065             // space at the end, the request has succeeded.
7066
7067             if ((current64 - ((UIntPtr)stackInfo.AllocationBase).ToUInt64()) > STACK_RESERVED_SPACE)
7068             {
7069                 m_lastKnownWatermark = current64;
7070                 return true;
7071             }
7072
7073             return false;
7074
7075 #else // !FEATURE_PAL && !PFX_LEGACY_3_5
7076
7077             // if we're being compiled with FEATURE_PAL or PFX_LEGACY_3_5 we simply allow unchecked inlining.
7078             return true;
7079 #endif
7080         }
7081     }
7082
7083     // Special internal struct that we use to signify that we are not interested in
7084     // a Task<VoidTaskResult>'s result.
7085     internal struct VoidTaskResult { }
7086
7087     // Interface to which all completion actions must conform.
7088     // This interface allows us to combine functionality and reduce allocations.
7089     // For example, see Task.SetOnInvokeMres, and its use in Task.SpinThenBlockingWait().
7090     // This code:
7091     //      ManualResetEvent mres = new ManualResetEventSlim(false, 0);
7092     //      Action<Task> completionAction = delegate { mres.Set() ; };
7093     //      AddCompletionAction(completionAction);
7094     // gets replaced with this:
7095     //      SetOnInvokeMres mres = new SetOnInvokeMres();
7096     //      AddCompletionAction(mres);
7097     // For additional examples of where this is used, see internal classes Task.SignalOnInvokeCDE,
7098     // Task.WhenAllPromise, Task.WhenAllPromise<T>, TaskFactory.CompleteOnCountdownPromise,
7099     // TaskFactory.CompleteOnCountdownPromise<T>, and TaskFactory.CompleteOnInvokePromise.
7100     internal interface ITaskCompletionAction
7101     {
7102         void Invoke(Task completingTask);
7103     }
7104
7105     // This class encapsulates all "unwrap" logic, and also implements ITaskCompletionAction,
7106     // which minimizes the allocations needed for queuing it to its antecedent.  This
7107     // logic is used by both the Unwrap extension methods and the unwrap-style Task.Run methods.
7108     internal sealed class UnwrapPromise<TResult> : Task<TResult>, ITaskCompletionAction
7109     {
7110         // The possible states for our UnwrapPromise, used by Invoke() to determine which logic to execute
7111         private const byte STATE_WAITING_ON_OUTER_TASK = 0; // Invoke() means "process completed outer task"
7112         private const byte STATE_WAITING_ON_INNER_TASK = 1; // Invoke() means "process completed inner task"
7113         private const byte STATE_DONE = 2;                  // Invoke() means "something went wrong and we are hosed!"
7114
7115         // Keep track of our state; initialized to STATE_WAITING_ON_OUTER_TASK in the constructor
7116         private byte _state;
7117
7118         // "Should we check for OperationCanceledExceptions on the outer task and interpret them as proxy cancellation?"
7119         // Unwrap() sets this to false, Run() sets it to true.
7120         private readonly bool _lookForOce;
7121
7122         public UnwrapPromise(Task outerTask, bool lookForOce)
7123             : base((object)null, outerTask.CreationOptions & TaskCreationOptions.AttachedToParent)
7124         {
7125             Contract.Requires(outerTask != null, "Expected non-null outerTask");
7126             _lookForOce = lookForOce;
7127             _state = STATE_WAITING_ON_OUTER_TASK;
7128
7129             if (AsyncCausalityTracer.LoggingOn)
7130                 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task.Unwrap", 0);
7131
7132             if (Task.s_asyncDebuggingEnabled)
7133             {
7134                 AddToActiveTasks(this);
7135             }
7136
7137             // Link ourselves to the outer task.
7138             // If the outer task has already completed, take the fast path
7139             // of immediately transferring its results or processing the inner task.
7140             if (outerTask.IsCompleted)
7141             {
7142                 ProcessCompletedOuterTask(outerTask);
7143             }
7144             else // Otherwise, process its completion asynchronously.
7145             {
7146                 outerTask.AddCompletionAction(this);
7147             }
7148         }
7149
7150         // For ITaskCompletionAction 
7151         public void Invoke(Task completingTask)
7152         {
7153             // Check the current stack guard.  If we're ok to inline,
7154             // process the task, and reset the guard when we're done.
7155             var sg = Task.CurrentStackGuard;
7156             if (sg.TryBeginInliningScope())
7157             {
7158                 try { InvokeCore(completingTask); }
7159                 finally { sg.EndInliningScope(); }
7160             }
7161             // Otherwise, we're too deep on the stack, and
7162             // we shouldn't run the continuation chain here, so queue a work
7163             // item to call back here to Invoke asynchronously.
7164             else InvokeCoreAsync(completingTask);
7165         }
7166
7167         /// <summary>
7168         /// Processes the completed task. InvokeCore could be called twice:
7169         /// once for the outer task, once for the inner task.
7170         /// </summary>
7171         /// <param name="completingTask">The completing outer or inner task.</param>
7172         private void InvokeCore(Task completingTask)
7173         {
7174             switch (_state)
7175             {
7176                 case STATE_WAITING_ON_OUTER_TASK:
7177                     ProcessCompletedOuterTask(completingTask);
7178                     // We bump the state inside of ProcessCompletedOuterTask because it can also be called from the constructor.
7179                     break;
7180                 case STATE_WAITING_ON_INNER_TASK:
7181                     bool result = TrySetFromTask(completingTask, lookForOce: false);
7182                     _state = STATE_DONE; // bump the state
7183                     Contract.Assert(result, "Expected TrySetFromTask from inner task to succeed");
7184                     break;
7185                 default:
7186                     Contract.Assert(false, "UnwrapPromise in illegal state");
7187                     break;
7188             }
7189         }
7190
7191         // Calls InvokeCore asynchronously.
7192         [SecuritySafeCritical]
7193         private void InvokeCoreAsync(Task completingTask)
7194         {
7195             // Queue a call to Invoke.  If we're so deep on the stack that we're at risk of overflowing,
7196             // there's a high liklihood this thread is going to be doing lots more work before
7197             // returning to the thread pool (at the very least unwinding through thousands of
7198             // stack frames).  So we queue to the global queue.
7199             ThreadPool.UnsafeQueueUserWorkItem(state =>
7200             {
7201                 // InvokeCore(completingTask);
7202                 var tuple = (Tuple<UnwrapPromise<TResult>, Task>)state;
7203                 tuple.Item1.InvokeCore(tuple.Item2);
7204             }, Tuple.Create<UnwrapPromise<TResult>, Task>(this, completingTask));
7205         }
7206
7207         /// <summary>Processes the outer task once it's completed.</summary>
7208         /// <param name="task">The now-completed outer task.</param>
7209         private void ProcessCompletedOuterTask(Task task)
7210         {
7211             Contract.Requires(task != null && task.IsCompleted, "Expected non-null, completed outer task");
7212             Contract.Assert(_state == STATE_WAITING_ON_OUTER_TASK, "We're in the wrong state!");
7213
7214             // Bump our state before proceeding any further
7215             _state = STATE_WAITING_ON_INNER_TASK;
7216
7217             switch (task.Status)
7218             {
7219                 // If the outer task did not complete successfully, then record the 
7220                 // cancellation/fault information to tcs.Task.
7221                 case TaskStatus.Canceled:
7222                 case TaskStatus.Faulted:
7223                     bool result = TrySetFromTask(task, _lookForOce);
7224                     Contract.Assert(result, "Expected TrySetFromTask from outer task to succeed");
7225                     break;
7226
7227                 // Otherwise, process the inner task it returned.
7228                 case TaskStatus.RanToCompletion:
7229                     var taskOfTaskOfTResult = task as Task<Task<TResult>>; // it's either a Task<Task> or Task<Task<TResult>>
7230                     ProcessInnerTask(taskOfTaskOfTResult != null ?
7231                         taskOfTaskOfTResult.Result : ((Task<Task>)task).Result);
7232                     break;
7233             }
7234         }
7235
7236         /// <summary>Transfer the completion status from "task" to ourself.</summary>
7237         /// <param name="task">The source task whose results should be transfered to <paramref name="promise"/>.</param>
7238         /// <param name="lookForOce">Whether or not to look for OperationCanceledExceptions in task's exceptions if it faults.</param>
7239         /// <returns>true if the transfer was successful; otherwise, false.</returns>
7240         private bool TrySetFromTask(Task task, bool lookForOce)
7241         {
7242             Contract.Requires(task != null && task.IsCompleted, "TrySetFromTask: Expected task to have completed.");
7243
7244             if (AsyncCausalityTracer.LoggingOn)
7245                 AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Join);
7246
7247             bool result = false;
7248             switch (task.Status)
7249             {
7250                 case TaskStatus.Canceled:
7251                     result = TrySetCanceled(task.CancellationToken, task.GetCancellationExceptionDispatchInfo());
7252                     break;
7253
7254                 case TaskStatus.Faulted:
7255                     var edis = task.GetExceptionDispatchInfos();
7256                     ExceptionDispatchInfo oceEdi;
7257                     OperationCanceledException oce;
7258                     if (lookForOce && edis.Count > 0 &&
7259                         (oceEdi = edis[0]) != null &&
7260                         (oce = oceEdi.SourceException as OperationCanceledException) != null)
7261                     {
7262                         result = TrySetCanceled(oce.CancellationToken, oceEdi);
7263                     }
7264                     else
7265                     {
7266                         result = TrySetException(edis);
7267                     }
7268                     break;
7269
7270                 case TaskStatus.RanToCompletion:
7271                     var taskTResult = task as Task<TResult>;
7272
7273                     if (AsyncCausalityTracer.LoggingOn)
7274                         AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
7275
7276                     if (Task.s_asyncDebuggingEnabled)
7277                     {
7278                         RemoveFromActiveTasks(this.Id);
7279                     }
7280
7281                     result = TrySetResult(taskTResult != null ? taskTResult.Result : default(TResult));
7282                     break;
7283             }
7284             return result;
7285         }
7286
7287         /// <summary>
7288         /// Processes the inner task of a Task{Task} or Task{Task{TResult}}, 
7289         /// transferring the appropriate results to ourself.
7290         /// </summary>
7291         /// <param name="task">The inner task returned by the task provided by the user.</param>
7292         private void ProcessInnerTask(Task task)
7293         {
7294             // If the inner task is null, the proxy should be canceled.
7295             if (task == null)
7296             {
7297                 TrySetCanceled(default(CancellationToken));
7298                 _state = STATE_DONE; // ... and record that we are done
7299             }
7300
7301             // Fast path for if the inner task is already completed
7302             else if (task.IsCompleted)
7303             {
7304                 TrySetFromTask(task, lookForOce: false);
7305                 _state = STATE_DONE; // ... and record that we are done
7306             }
7307
7308             // The inner task exists but is not yet complete, so when it does complete,
7309             // take some action to set our completion state.
7310             else
7311             {
7312                 task.AddCompletionAction(this);
7313                 // We'll record that we are done when Invoke() is called.
7314             }
7315         }
7316
7317     }
7318
7319
7320 }