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