afe64ec37d0354e618704ecadee802efb13bd193
[mono.git] / mcs / class / referencesource / mscorlib / system / threading / Tasks / FutureFactory.cs
1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
7 //
8 // FutureFactory.cs
9 //
10 // <OWNER>Microsoft</OWNER>
11 //
12 // As with TaskFactory, TaskFactory<TResult> encodes common factory patterns into helper methods.
13 //
14 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
15
16 using System;
17 using System.Security;
18 using System.Security.Permissions;
19 using System.Runtime.CompilerServices;
20 using System.Threading;
21 using System.Diagnostics.Contracts;
22 using System.Runtime.Versioning;
23
24 namespace System.Threading.Tasks
25 {
26     /// <summary>
27     /// Provides support for creating and scheduling
28     /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task{TResult}</see> objects.
29     /// </summary>
30     /// <typeparam name="TResult">The type of the results that are available though 
31     /// the <see cref="T:System.Threading.Tasks.Task{TResult}">Task{TResult}</see> objects that are associated with 
32     /// the methods in this class.</typeparam>
33     /// <remarks>
34     /// <para>
35     /// There are many common patterns for which tasks are relevant. The <see cref="TaskFactory{TResult}"/>
36     /// class encodes some of these patterns into methods that pick up default settings, which are
37     /// configurable through its constructors.
38     /// </para>
39     /// <para>
40     /// A default instance of <see cref="TaskFactory{TResult}"/> is available through the
41     /// <see cref="System.Threading.Tasks.Task{TResult}.Factory">Task{TResult}.Factory</see> property.
42     /// </para>
43     /// </remarks>
44     [HostProtection(Synchronization = true, ExternalThreading = true)]
45     public class TaskFactory<TResult>
46     {
47         // Member variables, DefaultScheduler, other properties and ctors 
48         // copied right out of TaskFactory...  Lots of duplication here...
49         // Should we be thinking about a TaskFactoryBase class?
50
51         // member variables
52         private CancellationToken m_defaultCancellationToken;
53         private TaskScheduler m_defaultScheduler;
54         private TaskCreationOptions m_defaultCreationOptions;
55         private TaskContinuationOptions m_defaultContinuationOptions;
56
57         private TaskScheduler DefaultScheduler
58         {
59             get
60             {
61                 if (m_defaultScheduler == null) return TaskScheduler.Current;
62                 else return m_defaultScheduler;
63             }
64         }
65
66         // sister method to above property -- avoids a TLS lookup
67         private TaskScheduler GetDefaultScheduler(Task currTask)
68         {
69             if (m_defaultScheduler != null) return m_defaultScheduler;
70             else if ((currTask != null)
71                 && ((currTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
72                 )
73                 return currTask.ExecutingTaskScheduler;
74             else return TaskScheduler.Default;
75         }
76
77         /* Constructors */
78
79         /// <summary>
80         /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the default configuration.
81         /// </summary>
82         /// <remarks>
83         /// This constructor creates a <see cref="TaskFactory{TResult}"/> instance with a default configuration. The
84         /// <see cref="TaskCreationOptions"/> property is initialized to
85         /// <see cref="System.Threading.Tasks.TaskCreationOptions.None">TaskCreationOptions.None</see>, the
86         /// <see cref="TaskContinuationOptions"/> property is initialized to <see
87         /// cref="System.Threading.Tasks.TaskContinuationOptions.None">TaskContinuationOptions.None</see>,
88         /// and the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is
89         /// initialized to the current scheduler (see <see
90         /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
91         /// </remarks>
92         public TaskFactory()
93             : this(default(CancellationToken), TaskCreationOptions.None, TaskContinuationOptions.None, null)
94         {
95         }
96
97         /// <summary>
98         /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the default configuration.
99         /// </summary>
100         /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned 
101         /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified 
102         /// while calling the factory methods.</param>
103         /// <remarks>
104         /// This constructor creates a <see cref="TaskFactory{TResult}"/> instance with a default configuration. The
105         /// <see cref="TaskCreationOptions"/> property is initialized to
106         /// <see cref="System.Threading.Tasks.TaskCreationOptions.None">TaskCreationOptions.None</see>, the
107         /// <see cref="TaskContinuationOptions"/> property is initialized to <see
108         /// cref="System.Threading.Tasks.TaskContinuationOptions.None">TaskContinuationOptions.None</see>,
109         /// and the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is
110         /// initialized to the current scheduler (see <see
111         /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
112         /// </remarks>
113         public TaskFactory(CancellationToken cancellationToken)
114             : this(cancellationToken, TaskCreationOptions.None, TaskContinuationOptions.None, null)
115         {
116         }
117
118         /// <summary>
119         /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the specified configuration.
120         /// </summary>
121         /// <param name="scheduler">
122         /// The <see cref="System.Threading.Tasks.TaskScheduler">
123         /// TaskScheduler</see> to use to schedule any tasks created with this TaskFactory{TResult}. A null value
124         /// indicates that the current TaskScheduler should be used.
125         /// </param>
126         /// <remarks>
127         /// With this constructor, the
128         /// <see cref="TaskCreationOptions"/> property is initialized to
129         /// <see cref="System.Threading.Tasks.TaskCreationOptions.None">TaskCreationOptions.None</see>, the
130         /// <see cref="TaskContinuationOptions"/> property is initialized to <see
131         /// cref="System.Threading.Tasks.TaskContinuationOptions.None">TaskContinuationOptions.None</see>,
132         /// and the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is
133         /// initialized to <paramref name="scheduler"/>, unless it's null, in which case the property is
134         /// initialized to the current scheduler (see <see
135         /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
136         /// </remarks>
137         public TaskFactory(TaskScheduler scheduler) // null means to use TaskScheduler.Current
138             : this(default(CancellationToken), TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
139         {
140         }
141
142         /// <summary>
143         /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the specified configuration.
144         /// </summary>
145         /// <param name="creationOptions">
146         /// The default <see cref="System.Threading.Tasks.TaskCreationOptions">
147         /// TaskCreationOptions</see> to use when creating tasks with this TaskFactory{TResult}.
148         /// </param>
149         /// <param name="continuationOptions">
150         /// The default <see cref="System.Threading.Tasks.TaskContinuationOptions">
151         /// TaskContinuationOptions</see> to use when creating continuation tasks with this TaskFactory{TResult}.
152         /// </param>
153         /// <exception cref="T:System.ArgumentOutOfRangeException">
154         /// The exception that is thrown when the
155         /// <paramref name="creationOptions"/> argument or the <paramref name="continuationOptions"/>
156         /// argument specifies an invalid value.
157         /// </exception>
158         /// <remarks>
159         /// With this constructor, the
160         /// <see cref="TaskCreationOptions"/> property is initialized to <paramref name="creationOptions"/>,
161         /// the
162         /// <see cref="TaskContinuationOptions"/> property is initialized to <paramref
163         /// name="continuationOptions"/>, and the <see
164         /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is initialized to the
165         /// current scheduler (see <see
166         /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
167         /// </remarks>
168         public TaskFactory(TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions)
169             : this(default(CancellationToken), creationOptions, continuationOptions, null)
170         {
171         }
172
173         /// <summary>
174         /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the specified configuration.
175         /// </summary>
176         /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned 
177         /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified 
178         /// while calling the factory methods.</param>
179         /// <param name="creationOptions">
180         /// The default <see cref="System.Threading.Tasks.TaskCreationOptions">
181         /// TaskCreationOptions</see> to use when creating tasks with this TaskFactory{TResult}.
182         /// </param>
183         /// <param name="continuationOptions">
184         /// The default <see cref="System.Threading.Tasks.TaskContinuationOptions">
185         /// TaskContinuationOptions</see> to use when creating continuation tasks with this TaskFactory{TResult}.
186         /// </param>
187         /// <param name="scheduler">
188         /// The default <see cref="System.Threading.Tasks.TaskScheduler">
189         /// TaskScheduler</see> to use to schedule any Tasks created with this TaskFactory{TResult}. A null value
190         /// indicates that TaskScheduler.Current should be used.
191         /// </param>
192         /// <exception cref="T:System.ArgumentOutOfRangeException">
193         /// The exception that is thrown when the
194         /// <paramref name="creationOptions"/> argument or the <paramref name="continuationOptions"/>
195         /// argumentspecifies an invalid value.
196         /// </exception>
197         /// <remarks>
198         /// With this constructor, the
199         /// <see cref="TaskCreationOptions"/> property is initialized to <paramref name="creationOptions"/>,
200         /// the
201         /// <see cref="TaskContinuationOptions"/> property is initialized to <paramref
202         /// name="continuationOptions"/>, and the <see
203         /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is initialized to
204         /// <paramref name="scheduler"/>, unless it's null, in which case the property is initialized to the
205         /// current scheduler (see <see
206         /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
207         /// </remarks>
208         public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
209         {
210             TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
211             TaskFactory.CheckCreationOptions(creationOptions);
212
213             m_defaultCancellationToken = cancellationToken;
214             m_defaultScheduler = scheduler;
215             m_defaultCreationOptions = creationOptions;
216             m_defaultContinuationOptions = continuationOptions;
217         }
218
219         /* Properties */
220
221         /// <summary>
222         /// Gets the default <see cref="System.Threading.CancellationToken">CancellationToken</see> of this
223         /// TaskFactory.
224         /// </summary>
225         /// <remarks>
226         /// This property returns the default <see cref="CancellationToken"/> that will be assigned to all 
227         /// tasks created by this factory unless another CancellationToken value is explicitly specified 
228         /// during the call to the factory methods.
229         /// </remarks>
230         public CancellationToken CancellationToken { get { return m_defaultCancellationToken; } }
231
232         /// <summary>
233         /// Gets the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> of this
234         /// TaskFactory{TResult}.
235         /// </summary>
236         /// <remarks>
237         /// This property returns the default scheduler for this factory.  It will be used to schedule all 
238         /// tasks unless another scheduler is explicitly specified during calls to this factory's methods.  
239         /// If null, <see cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see> 
240         /// will be used.
241         /// </remarks>
242         public TaskScheduler Scheduler { get { return m_defaultScheduler; } }
243
244         /// <summary>
245         /// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions
246         /// </see> value of this TaskFactory{TResult}.
247         /// </summary>
248         /// <remarks>
249         /// This property returns the default creation options for this factory.  They will be used to create all 
250         /// tasks unless other options are explicitly specified during calls to this factory's methods.
251         /// </remarks>
252         public TaskCreationOptions CreationOptions { get { return m_defaultCreationOptions; } }
253
254         /// <summary>
255         /// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskContinuationOptions
256         /// </see> value of this TaskFactory{TResult}.
257         /// </summary>
258         /// <remarks>
259         /// This property returns the default continuation options for this factory.  They will be used to create 
260         /// all continuation tasks unless other options are explicitly specified during calls to this factory's methods.
261         /// </remarks>
262         public TaskContinuationOptions ContinuationOptions { get { return m_defaultContinuationOptions; } }
263
264
265         /* StartNew */
266
267         /// <summary>
268         /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
269         /// </summary>
270         /// <param name="function">A function delegate that returns the future result to be available through
271         /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
272         /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
273         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
274         /// name="function"/>
275         /// argument is null.</exception>
276         /// <remarks>
277         /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
278         /// of its constructors and then calling
279         /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
280         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
281         /// for both simplicity and performance.
282         /// </remarks>
283         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
284         public Task<TResult> StartNew(Func<TResult> function)
285         {
286             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
287             Task currTask = Task.InternalCurrent;
288             return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
289                 m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
290         }
291
292         /// <summary>
293         /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
294         /// </summary>
295         /// <param name="function">A function delegate that returns the future result to be available through
296         /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
297         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
298         /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
299         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
300         /// name="function"/>
301         /// argument is null.</exception>
302         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
303         /// has already been disposed.
304         /// </exception>
305         /// <remarks>
306         /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
307         /// of its constructors and then calling
308         /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
309         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
310         /// for both simplicity and performance.
311         /// </remarks>
312         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
313         public Task<TResult> StartNew(Func<TResult> function, CancellationToken cancellationToken)
314         {
315             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
316             Task currTask = Task.InternalCurrent;
317             return Task<TResult>.StartNew(currTask, function, cancellationToken,
318                 m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
319         }
320
321         /// <summary>
322         /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
323         /// </summary>
324         /// <param name="function">A function delegate that returns the future result to be available through
325         /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
326         /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
327         /// created
328         /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
329         /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
330         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
331         /// name="function"/>
332         /// argument is null.</exception>
333         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
334         /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
335         /// value.</exception>
336         /// <remarks>
337         /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
338         /// of its constructors and then calling
339         /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
340         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
341         /// for both simplicity and performance.
342         /// </remarks>
343         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
344         public Task<TResult> StartNew(Func<TResult> function, TaskCreationOptions creationOptions)
345         {
346             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
347             Task currTask = Task.InternalCurrent;
348             return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
349                 creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
350         }
351
352         /// <summary>
353         /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
354         /// </summary>
355         /// <param name="function">A function delegate that returns the future result to be available through
356         /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
357         /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
358         /// created
359         /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
360         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
361         /// <param name="scheduler">The <see
362         /// cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
363         /// that is used to schedule the created <see cref="T:System.Threading.Tasks.Task{TResult}">
364         /// Task{TResult}</see>.</param>
365         /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
366         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
367         /// name="function"/>
368         /// argument is null.</exception>
369         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
370         /// name="scheduler"/>
371         /// argument is null.</exception>
372         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
373         /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
374         /// value.</exception>
375         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
376         /// has already been disposed.
377         /// </exception>
378         /// <remarks>
379         /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
380         /// of its constructors and then calling
381         /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
382         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
383         /// for both simplicity and performance.
384         /// </remarks>
385         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
386         public Task<TResult> StartNew(Func<TResult> function, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
387         {
388             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
389             return Task<TResult>.StartNew(
390                 Task.InternalCurrentIfAttached(creationOptions), function, cancellationToken,
391                 creationOptions, InternalTaskOptions.None, scheduler, ref stackMark);
392         }
393
394         /// <summary>
395         /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
396         /// </summary>
397         /// <param name="function">A function delegate that returns the future result to be available through
398         /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
399         /// <param name="state">An object containing data to be used by the <paramref name="function"/>
400         /// delegate.</param>
401         /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
402         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
403         /// name="function"/>
404         /// argument is null.</exception>
405         /// <remarks>
406         /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
407         /// of its constructors and then calling
408         /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
409         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
410         /// for both simplicity and performance.
411         /// </remarks>
412         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
413         public Task<TResult> StartNew(Func<Object, TResult> function, Object state)
414         {
415             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
416             Task currTask = Task.InternalCurrent;
417             return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
418                 m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
419         }
420
421         /// <summary>
422         /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
423         /// </summary>
424         /// <param name="function">A function delegate that returns the future result to be available through
425         /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
426         /// <param name="state">An object containing data to be used by the <paramref name="function"/>
427         /// delegate.</param>
428         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
429         /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
430         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
431         /// name="function"/>
432         /// argument is null.</exception>
433         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
434         /// has already been disposed.
435         /// </exception>
436         /// <remarks>
437         /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
438         /// of its constructors and then calling
439         /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
440         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
441         /// for both simplicity and performance.
442         /// </remarks>
443         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
444         public Task<TResult> StartNew(Func<Object, TResult> function, Object state, CancellationToken cancellationToken)
445         {
446             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
447             Task currTask = Task.InternalCurrent;
448             return Task<TResult>.StartNew(currTask, function, state, cancellationToken,
449                 m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
450         }
451
452         /// <summary>
453         /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
454         /// </summary>
455         /// <param name="function">A function delegate that returns the future result to be available through
456         /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
457         /// <param name="state">An object containing data to be used by the <paramref name="function"/>
458         /// delegate.</param>
459         /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
460         /// created
461         /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
462         /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
463         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
464         /// name="function"/>
465         /// argument is null.</exception>
466         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
467         /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
468         /// value.</exception>
469         /// <remarks>
470         /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
471         /// of its constructors and then calling
472         /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
473         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
474         /// for both simplicity and performance.
475         /// </remarks>
476         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
477         public Task<TResult> StartNew(Func<Object, TResult> function, Object state, TaskCreationOptions creationOptions)
478         {
479             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
480             Task currTask = Task.InternalCurrent;
481             return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
482                 creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
483         }
484
485         /// <summary>
486         /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
487         /// </summary>
488         /// <param name="function">A function delegate that returns the future result to be available through
489         /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
490         /// <param name="state">An object containing data to be used by the <paramref name="function"/>
491         /// delegate.</param>
492         /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
493         /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
494         /// created
495         /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
496         /// <param name="scheduler">The <see
497         /// cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
498         /// that is used to schedule the created <see cref="T:System.Threading.Tasks.Task{TResult}">
499         /// Task{TResult}</see>.</param>
500         /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
501         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
502         /// name="function"/>
503         /// argument is null.</exception>
504         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
505         /// name="scheduler"/>
506         /// argument is null.</exception>
507         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
508         /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
509         /// value.</exception>
510         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
511         /// has already been disposed.
512         /// </exception>
513         /// <remarks>
514         /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
515         /// of its constructors and then calling
516         /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
517         /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
518         /// for both simplicity and performance.
519         /// </remarks>
520         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
521         public Task<TResult> StartNew(Func<Object, TResult> function, Object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
522         {
523             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
524             return Task<TResult>.StartNew(Task.InternalCurrentIfAttached(creationOptions), function, state, cancellationToken,
525                 creationOptions, InternalTaskOptions.None, scheduler, ref stackMark);
526         }
527
528         //
529         // APM Factory methods
530         //
531
532         // Common core logic for FromAsync calls.  This minimizes the chance of "drift" between overload implementations.
533         private static void FromAsyncCoreLogic(
534             IAsyncResult iar,
535             Func<IAsyncResult, TResult> endFunction,
536             Action<IAsyncResult> endAction,
537             Task<TResult> promise,
538             bool requiresSynchronization)
539         {
540             Contract.Requires((endFunction != null) != (endAction != null), "Expected exactly one of endFunction/endAction to be non-null");
541
542             Exception ex = null;
543             OperationCanceledException oce = null;
544             TResult result = default(TResult);
545
546             try
547             {
548                 if (endFunction != null)
549                 {
550                     result = endFunction(iar);
551                 }
552                 else
553                 {
554                     endAction(iar);
555                 }
556             }
557             catch (OperationCanceledException _oce) { oce = _oce; }
558             catch (Exception e) { ex = e; }
559             finally
560             {
561                 if (oce != null)
562                 {
563                     promise.TrySetCanceled(oce.CancellationToken, oce);
564                 }
565                 else if (ex != null)
566                 {
567                     bool bWonSetException = promise.TrySetException(ex);
568                     if (bWonSetException && ex is ThreadAbortException)
569                     {
570                         promise.m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false);
571                     }
572                 }
573                 else
574                 {
575                     if (AsyncCausalityTracer.LoggingOn)
576                         AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Completed);
577
578                     if (Task.s_asyncDebuggingEnabled)
579                     {
580                         Task.RemoveFromActiveTasks(promise.Id);
581                     }
582                     if (requiresSynchronization)
583                     {
584                         promise.TrySetResult(result);
585                     }
586                     else
587                     {
588                         promise.DangerousSetResult(result);
589                     }
590                 }
591                 
592                
593             }
594         }
595
596         /// <summary>
597         /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that executes an end
598         /// method function when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes.
599         /// </summary>
600         /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the
601         /// <paramref name="endMethod"/>.</param>
602         /// <param name="endMethod">The function delegate that processes the completed <paramref
603         /// name="asyncResult"/>.</param>
604         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
605         /// <paramref name="asyncResult"/> argument is null.</exception>
606         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
607         /// <paramref name="endMethod"/> argument is null.</exception>
608         /// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
609         /// asynchronous operation.</returns>
610         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
611         public Task<TResult> FromAsync(IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod)
612         {
613             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
614             return FromAsyncImpl(asyncResult, endMethod, null, m_defaultCreationOptions, DefaultScheduler, ref stackMark);
615         }
616
617         /// <summary>
618         /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that executes an end
619         /// method function when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes.
620         /// </summary>
621         /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the
622         /// <paramref name="endMethod"/>.</param>
623         /// <param name="endMethod">The function delegate that processes the completed <paramref
624         /// name="asyncResult"/>.</param>
625         /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
626         /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
627         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
628         /// <paramref name="asyncResult"/> argument is null.</exception>
629         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
630         /// <paramref name="endMethod"/> argument is null.</exception>
631         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
632         /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
633         /// value.</exception>
634         /// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
635         /// asynchronous operation.</returns>
636         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
637         public Task<TResult> FromAsync(
638             IAsyncResult asyncResult,
639             Func<IAsyncResult, TResult> endMethod,
640             TaskCreationOptions creationOptions)
641         {
642             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
643             return FromAsyncImpl(asyncResult, endMethod, null, creationOptions, DefaultScheduler, ref stackMark);
644         }
645
646
647
648         /// <summary>
649         /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that executes an end
650         /// method function when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes.
651         /// </summary>
652         /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the
653         /// <paramref name="endMethod"/>.</param>
654         /// <param name="endMethod">The function delegate that processes the completed <paramref
655         /// name="asyncResult"/>.</param>
656         /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
657         /// that is used to schedule the task that executes the end method.</param>
658         /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
659         /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
660         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
661         /// <paramref name="asyncResult"/> argument is null.</exception>
662         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
663         /// <paramref name="endMethod"/> argument is null.</exception>
664         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
665         /// <paramref name="scheduler"/> argument is null.</exception>
666         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
667         /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
668         /// value.</exception>
669         /// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
670         /// asynchronous operation.</returns>
671         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
672         public Task<TResult> FromAsync(
673             IAsyncResult asyncResult,
674             Func<IAsyncResult, TResult> endMethod,
675             TaskCreationOptions creationOptions,
676             TaskScheduler scheduler)
677         {
678             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
679             return FromAsyncImpl(asyncResult, endMethod, null, creationOptions, scheduler, ref stackMark);
680         }
681
682         // internal overload that supports StackCrawlMark
683         // We also need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
684         // method can access the logic w/o declaring a TaskFactory<TResult> instance.
685         internal static Task<TResult> FromAsyncImpl(
686             IAsyncResult asyncResult,
687             Func<IAsyncResult, TResult> endFunction,
688             Action<IAsyncResult> endAction,
689             TaskCreationOptions creationOptions,
690             TaskScheduler scheduler,
691             ref StackCrawlMark stackMark)
692         {
693             if (asyncResult == null)
694                 throw new ArgumentNullException("asyncResult");
695
696             if (endFunction == null && endAction == null)
697                 throw new ArgumentNullException("endMethod");
698
699             Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
700
701             if (scheduler == null)
702                 throw new ArgumentNullException("scheduler");
703             Contract.EndContractBlock();
704
705             TaskFactory.CheckFromAsyncOptions(creationOptions, false);
706
707             Task<TResult> promise = new Task<TResult>((object)null, creationOptions);
708
709             if (AsyncCausalityTracer.LoggingOn)
710                 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync", 0);
711
712             if (Task.s_asyncDebuggingEnabled)
713             {
714                 Task.AddToActiveTasks(promise);
715             }
716
717             // Just specify this task as detached. No matter what happens, we want endMethod 
718             // to be called -- even if the parent is canceled.  So we don't want to flow 
719             // RespectParentCancellation.
720             Task t = new Task(delegate
721             {
722                 FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization:true);
723             },
724                 (object)null, null,
725                 default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null, ref stackMark);
726
727             if (AsyncCausalityTracer.LoggingOn)
728                 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Verbose, t.Id, "TaskFactory.FromAsync Callback", 0);
729
730             if (Task.s_asyncDebuggingEnabled)
731             {
732                 Task.AddToActiveTasks(t);
733             }
734
735             if (asyncResult.IsCompleted)
736             {
737                 try { t.InternalRunSynchronously(scheduler, waitForCompletion:false); }
738                 catch (Exception e) { promise.TrySetException(e); } // catch and log any scheduler exceptions
739             }
740             else
741             {
742                 ThreadPool.RegisterWaitForSingleObject(
743                     asyncResult.AsyncWaitHandle,
744                     delegate
745                     {
746                         try { t.InternalRunSynchronously(scheduler, waitForCompletion: false); }
747                         catch (Exception e) { promise.TrySetException(e); } // catch and log any scheduler exceptions
748                     },
749                     null,
750                     Timeout.Infinite,
751                     true);
752             }
753
754             return promise;
755         }
756
757         /// <summary>
758         /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
759         /// begin and end methods that conform to the Asynchronous Programming Model pattern.
760         /// </summary>
761         /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
762         /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
763         /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
764         /// delegate.</param>
765         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
766         /// <paramref name="beginMethod"/> argument is null.</exception>
767         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
768         /// <paramref name="endMethod"/> argument is null.</exception>
769         /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
770         /// represents the asynchronous operation.</returns>
771         /// <remarks>
772         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
773         /// </remarks>
774         public Task<TResult> FromAsync(
775             Func<AsyncCallback, object, IAsyncResult> beginMethod,
776             Func<IAsyncResult, TResult> endMethod, object state)
777         {
778             return FromAsyncImpl(beginMethod, endMethod, null, state, m_defaultCreationOptions);
779         }
780
781         /// <summary>
782         /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
783         /// begin and end methods that conform to the Asynchronous Programming Model pattern.
784         /// </summary>
785         /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
786         /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
787         /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
788         /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
789         /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
790         /// delegate.</param>
791         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
792         /// <paramref name="beginMethod"/> argument is null.</exception>
793         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
794         /// <paramref name="endMethod"/> argument is null.</exception>
795         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
796         /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
797         /// value.</exception>
798         /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
799         /// represents the asynchronous operation.</returns>
800         /// <remarks>
801         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
802         /// </remarks>
803         public Task<TResult> FromAsync(
804             Func<AsyncCallback, object, IAsyncResult> beginMethod,
805             Func<IAsyncResult, TResult> endMethod, object state, TaskCreationOptions creationOptions)
806         {
807             return FromAsyncImpl(beginMethod, endMethod, null, state, creationOptions);
808         }
809
810         // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
811         // method can access the logic w/o declaring a TaskFactory<TResult> instance.
812         internal static Task<TResult> FromAsyncImpl(Func<AsyncCallback, object, IAsyncResult> beginMethod,
813             Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
814             object state, TaskCreationOptions creationOptions)
815         {
816             if (beginMethod == null)
817                 throw new ArgumentNullException("beginMethod");
818
819             if (endFunction == null && endAction == null)
820                 throw new ArgumentNullException("endMethod");
821
822             Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
823             
824             TaskFactory.CheckFromAsyncOptions(creationOptions, true);
825
826             Task<TResult> promise = new Task<TResult>(state, creationOptions);
827
828             if (AsyncCausalityTracer.LoggingOn)
829                 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync: " + beginMethod.Method.Name, 0);
830
831             if (Task.s_asyncDebuggingEnabled)
832             {
833                 Task.AddToActiveTasks(promise);
834             }
835
836             try
837             {
838                 // Do NOT change the code below. 
839                 // 4.5 relies on the fact that IAsyncResult CompletedSynchronously flag needs to be set correctly,
840                 // sadly this has not been the case that is why the behaviour from 4.5 broke 4.0 buggy apps. Any other
841                 // change will likely brake 4.5 behavior so if possible never touch this code again.
842                 if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
843                 {
844                     var invoked = new AtomicBoolean ();
845                     //This is 4.5 behaviour
846                     //if we don't require synchronization, a faster set result path is taken
847                     var asyncResult = beginMethod(iar =>
848                     {
849                         if (invoked.TryRelaxedSet ())
850                             FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
851                     }, state);
852                     if (asyncResult != null && asyncResult.CompletedSynchronously && invoked.TryRelaxedSet ())
853                     {
854                         Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
855                         FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false);
856                     }
857                 }
858                 else
859                 {
860                     //This is the original 4.0 behaviour
861                     var asyncResult = beginMethod(iar =>
862                     {
863                         FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
864                     }, state);
865                 }
866             }
867             catch
868             {
869                 if (AsyncCausalityTracer.LoggingOn)
870                     AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Error);
871
872                 if (Task.s_asyncDebuggingEnabled)
873                 {
874                     Task.RemoveFromActiveTasks(promise.Id);
875                 }
876
877                 // Make sure we don't leave promise "dangling".
878                 promise.TrySetResult(default(TResult));
879                 throw;
880             }
881
882             return promise;
883         }
884
885         /// <summary>
886         /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
887         /// begin and end methods that conform to the Asynchronous Programming Model pattern.
888         /// </summary>
889         /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
890         /// name="beginMethod"/> delegate.</typeparam>
891         /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
892         /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
893         /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
894         /// delegate.</param>
895         /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
896         /// delegate.</param>
897         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
898         /// <paramref name="beginMethod"/> argument is null.</exception>
899         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
900         /// <paramref name="endMethod"/> argument is null.</exception>
901         /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
902         /// represents the asynchronous operation.</returns>
903         /// <remarks>
904         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
905         /// </remarks>
906         public Task<TResult> FromAsync<TArg1>(
907             Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
908             Func<IAsyncResult, TResult> endMethod,
909             TArg1 arg1, object state)
910         {
911             return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, m_defaultCreationOptions);
912         }
913
914         /// <summary>
915         /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
916         /// begin and end methods that conform to the Asynchronous Programming Model pattern.
917         /// </summary>
918         /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
919         /// name="beginMethod"/> delegate.</typeparam>
920         /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
921         /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
922         /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
923         /// delegate.</param>
924         /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
925         /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
926         /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
927         /// delegate.</param>
928         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
929         /// <paramref name="beginMethod"/> argument is null.</exception>
930         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
931         /// <paramref name="endMethod"/> argument is null.</exception>
932         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
933         /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
934         /// value.</exception>
935         /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
936         /// represents the asynchronous operation.</returns>
937         /// <remarks>
938         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
939         /// </remarks>
940         public Task<TResult> FromAsync<TArg1>(
941             Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
942             Func<IAsyncResult, TResult> endMethod,
943             TArg1 arg1, object state, TaskCreationOptions creationOptions)
944         {
945             return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, creationOptions);
946         }
947
948         // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
949         // method can access the logic w/o declaring a TaskFactory<TResult> instance.
950         internal static Task<TResult> FromAsyncImpl<TArg1>(Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
951             Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
952             TArg1 arg1, object state, TaskCreationOptions creationOptions)
953         {
954             if (beginMethod == null)
955                 throw new ArgumentNullException("beginMethod");
956
957             if (endFunction == null && endAction == null)
958                 throw new ArgumentNullException("endFunction");
959
960             Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
961
962             TaskFactory.CheckFromAsyncOptions(creationOptions, true);
963
964             Task<TResult> promise = new Task<TResult>(state, creationOptions);
965
966             if (AsyncCausalityTracer.LoggingOn)
967                 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync: " + beginMethod.Method.Name, 0);
968
969             if (Task.s_asyncDebuggingEnabled)
970             {
971                 Task.AddToActiveTasks(promise);
972             }
973
974             try
975             {
976                 // Do NOT change the code below. 
977                 // 4.5 relies on the fact that IAsyncResult CompletedSynchronously flag needs to be set correctly,
978                 // sadly this has not been the case that is why the behaviour from 4.5 broke 4.0 buggy apps. Any other
979                 // change will likely brake 4.5 behavior so if possible never touch this code again.
980                 if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
981                 {
982                     var invoked = new AtomicBoolean ();
983                     //if we don't require synchronization, a faster set result path is taken
984                     var asyncResult = beginMethod(arg1, iar =>
985                     {
986                         if (invoked.TryRelaxedSet ())
987                             FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
988                     }, state);
989                     if (asyncResult != null && asyncResult.CompletedSynchronously && invoked.TryRelaxedSet ())
990                     {
991                         Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
992                         FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false);
993                     }
994                 }
995                 else
996                 {
997                     //quirk for previous versions
998                     var asyncResult = beginMethod(arg1, iar =>
999                     {
1000                         FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
1001                     }, state);
1002                 }
1003             }
1004             catch
1005             {
1006
1007                 if (AsyncCausalityTracer.LoggingOn)
1008                     AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Error);
1009
1010                 if (Task.s_asyncDebuggingEnabled)
1011                 {
1012                     Task.RemoveFromActiveTasks(promise.Id);
1013                 }
1014
1015                 // Make sure we don't leave promise "dangling".
1016                 promise.TrySetResult(default(TResult));
1017                 throw;
1018             }
1019
1020             return promise;
1021         }
1022
1023         /// <summary>
1024         /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
1025         /// begin and end methods that conform to the Asynchronous Programming Model pattern.
1026         /// </summary>
1027         /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
1028         /// name="beginMethod"/> delegate.</typeparam>
1029         /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
1030         /// delegate.</typeparam>
1031         /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
1032         /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
1033         /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
1034         /// delegate.</param>
1035         /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
1036         /// delegate.</param>
1037         /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
1038         /// delegate.</param>
1039         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1040         /// <paramref name="beginMethod"/> argument is null.</exception>
1041         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1042         /// <paramref name="endMethod"/> argument is null.</exception>
1043         /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
1044         /// represents the asynchronous operation.</returns>
1045         /// <remarks>
1046         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
1047         /// </remarks>
1048         public Task<TResult> FromAsync<TArg1, TArg2>(
1049             Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
1050             Func<IAsyncResult, TResult> endMethod,
1051             TArg1 arg1, TArg2 arg2, object state)
1052         {
1053             return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, m_defaultCreationOptions);
1054         }
1055
1056         /// <summary>
1057         /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
1058         /// begin and end methods that conform to the Asynchronous Programming Model pattern.
1059         /// </summary>
1060         /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
1061         /// name="beginMethod"/> delegate.</typeparam>
1062         /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
1063         /// delegate.</typeparam>
1064         /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
1065         /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
1066         /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
1067         /// delegate.</param>
1068         /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
1069         /// delegate.</param>
1070         /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
1071         /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
1072         /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
1073         /// delegate.</param>
1074         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1075         /// <paramref name="beginMethod"/> argument is null.</exception>
1076         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1077         /// <paramref name="endMethod"/> argument is null.</exception>
1078         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
1079         /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
1080         /// value.</exception>
1081         /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
1082         /// represents the asynchronous operation.</returns>
1083         /// <remarks>
1084         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
1085         /// </remarks>
1086         public Task<TResult> FromAsync<TArg1, TArg2>(
1087             Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
1088             Func<IAsyncResult, TResult> endMethod,
1089             TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
1090         {
1091             return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, creationOptions);
1092         }
1093
1094         // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
1095         // method can access the logic w/o declaring a TaskFactory<TResult> instance.
1096         internal static Task<TResult> FromAsyncImpl<TArg1, TArg2>(Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
1097             Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
1098             TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
1099         {
1100             if (beginMethod == null)
1101                 throw new ArgumentNullException("beginMethod");
1102
1103             if (endFunction == null && endAction == null)
1104                 throw new ArgumentNullException("endMethod");
1105
1106             Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
1107
1108             TaskFactory.CheckFromAsyncOptions(creationOptions, true);
1109
1110             Task<TResult> promise = new Task<TResult>(state, creationOptions);
1111
1112             if (AsyncCausalityTracer.LoggingOn)
1113                 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync: " + beginMethod.Method.Name, 0);
1114
1115             if (Task.s_asyncDebuggingEnabled)
1116             {
1117                 Task.AddToActiveTasks(promise);
1118             }
1119
1120             try
1121             {
1122                 // Do NOT change the code below. 
1123                 // 4.5 relies on the fact that IAsyncResult CompletedSynchronously flag needs to be set correctly,
1124                 // sadly this has not been the case that is why the behaviour from 4.5 broke 4.0 buggy apps. Any other
1125                 // change will likely brake 4.5 behavior so if possible never touch this code again.
1126                 if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
1127                 {
1128                     var invoked = new AtomicBoolean ();
1129                     //if we don't require synchronization, a faster set result path is taken
1130                     var asyncResult = beginMethod(arg1, arg2, iar =>
1131                     {
1132                         if (invoked.TryRelaxedSet ())
1133                             FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
1134                     }, state);
1135                     if (asyncResult != null && asyncResult.CompletedSynchronously && invoked.TryRelaxedSet ())
1136                     {
1137                         Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
1138                         FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false);
1139                     }
1140                 }
1141                 else
1142                 {
1143                     //quirk for previous versions
1144                     var asyncResult = beginMethod(arg1, arg2, iar =>
1145                     {
1146                         FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
1147                     }, state);
1148                 }
1149             }
1150             catch
1151             {
1152                 if (AsyncCausalityTracer.LoggingOn)
1153                     AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Error);
1154
1155                 if (Task.s_asyncDebuggingEnabled)
1156                 {
1157                     Task.RemoveFromActiveTasks(promise.Id);
1158                 }
1159
1160                 // Make sure we don't leave promise "dangling".
1161                 promise.TrySetResult(default(TResult));
1162                 throw;
1163             }
1164
1165             return promise;
1166         }
1167
1168         /// <summary>
1169         /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
1170         /// begin and end methods that conform to the Asynchronous Programming Model pattern.
1171         /// </summary>
1172         /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
1173         /// name="beginMethod"/> delegate.</typeparam>
1174         /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
1175         /// delegate.</typeparam>
1176         /// <typeparam name="TArg3">The type of the third argument passed to <paramref name="beginMethod"/>
1177         /// delegate.</typeparam>
1178         /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
1179         /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
1180         /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
1181         /// delegate.</param>
1182         /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
1183         /// delegate.</param>
1184         /// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/>
1185         /// delegate.</param>
1186         /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
1187         /// delegate.</param>
1188         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1189         /// <paramref name="beginMethod"/> argument is null.</exception>
1190         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1191         /// <paramref name="endMethod"/> argument is null.</exception>
1192         /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
1193         /// represents the asynchronous operation.</returns>
1194         /// <remarks>
1195         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
1196         /// </remarks>
1197         public Task<TResult> FromAsync<TArg1, TArg2, TArg3>(
1198             Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
1199             Func<IAsyncResult, TResult> endMethod,
1200             TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
1201         {
1202             return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, m_defaultCreationOptions);
1203         }
1204
1205         /// <summary>
1206         /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
1207         /// begin and end methods that conform to the Asynchronous Programming Model pattern.
1208         /// </summary>
1209         /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
1210         /// name="beginMethod"/> delegate.</typeparam>
1211         /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
1212         /// delegate.</typeparam>
1213         /// <typeparam name="TArg3">The type of the third argument passed to <paramref name="beginMethod"/>
1214         /// delegate.</typeparam>
1215         /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
1216         /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
1217         /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
1218         /// delegate.</param>
1219         /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
1220         /// delegate.</param>
1221         /// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/>
1222         /// delegate.</param>
1223         /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
1224         /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
1225         /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
1226         /// delegate.</param>
1227         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1228         /// <paramref name="beginMethod"/> argument is null.</exception>
1229         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1230         /// <paramref name="endMethod"/> argument is null.</exception>
1231         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
1232         /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
1233         /// value.</exception>
1234         /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
1235         /// represents the asynchronous operation.</returns>
1236         /// <remarks>
1237         /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
1238         /// </remarks>
1239         public Task<TResult> FromAsync<TArg1, TArg2, TArg3>(
1240             Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
1241             Func<IAsyncResult, TResult> endMethod,
1242             TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
1243         {
1244             return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, creationOptions);
1245         }
1246
1247         // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
1248         // method can access the logic w/o declaring a TaskFactory<TResult> instance.
1249         internal static Task<TResult> FromAsyncImpl<TArg1, TArg2, TArg3>(Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
1250             Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
1251             TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
1252         {
1253             if (beginMethod == null)
1254                 throw new ArgumentNullException("beginMethod");
1255
1256             if (endFunction == null && endAction == null)
1257                 throw new ArgumentNullException("endMethod");
1258
1259             Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
1260
1261             TaskFactory.CheckFromAsyncOptions(creationOptions, true);
1262
1263             Task<TResult> promise = new Task<TResult>(state, creationOptions);
1264
1265             if (AsyncCausalityTracer.LoggingOn)
1266                 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync: " + beginMethod.Method.Name, 0);
1267
1268             if (Task.s_asyncDebuggingEnabled)
1269             {
1270                 Task.AddToActiveTasks(promise);
1271             }
1272
1273             try
1274             {
1275                 // Do NOT change the code below. 
1276                 // 4.5 relies on the fact that IAsyncResult CompletedSynchronously flag needs to be set correctly,
1277                 // sadly this has not been the case that is why the behaviour from 4.5 broke 4.0 buggy apps. Any other
1278                 // change will likely brake 4.5 behavior so if possible never touch this code again.
1279                 if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
1280                 {
1281                     var invoked = new AtomicBoolean ();
1282                     //if we don't require synchronization, a faster set result path is taken
1283                     var asyncResult = beginMethod(arg1, arg2, arg3, iar =>
1284                     {
1285                         if (invoked.TryRelaxedSet ())
1286                             FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
1287                     }, state);
1288                     if (asyncResult != null && asyncResult.CompletedSynchronously && invoked.TryRelaxedSet ())
1289                     {
1290                         Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
1291                         FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false);
1292                     }
1293                 }
1294                 else
1295                 {
1296                     //quirk for previous versions
1297                     var asyncResult = beginMethod(arg1, arg2, arg3, iar =>
1298                     {
1299                         FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
1300                     }, state);
1301                 }
1302             }
1303             catch
1304             {
1305                 if (AsyncCausalityTracer.LoggingOn)
1306                     AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Error);
1307
1308                 if (Task.s_asyncDebuggingEnabled)
1309                 {
1310                     Task.RemoveFromActiveTasks(promise.Id);
1311                 }
1312
1313                 // Make sure we don't leave the promise "dangling".
1314                 promise.TrySetResult(default(TResult));
1315                 throw;
1316             }
1317
1318             return promise;
1319         }
1320
1321         /// <summary>
1322         /// Special internal-only FromAsync support used by System.IO to wrap
1323         /// APM implementations with minimal overhead, avoiding unnecessary closure
1324         /// and delegate allocations.
1325         /// </summary>
1326         /// <typeparam name="TInstance">Specifies the type of the instance on which the APM implementation lives.</typeparam>
1327         /// <typeparam name="TArg1">Specifies the type containing the arguments.</typeparam>
1328         /// <param name="thisRef">The instance from which the begin and end methods are invoked.</param>
1329         /// <param name="beginMethod">The begin method.</param>
1330         /// <param name="endMethod">The end method.</param>
1331         /// <param name="args">The arguments.</param>
1332         /// <returns>A task representing the asynchronous operation.</returns>
1333         internal static Task<TResult> FromAsyncTrim<TInstance, TArgs>(
1334             TInstance thisRef, TArgs args,
1335             Func<TInstance, TArgs, AsyncCallback, object, IAsyncResult> beginMethod,
1336             Func<TInstance, IAsyncResult, TResult> endMethod) 
1337             where TInstance : class
1338         {
1339             // Validate arguments, but only with asserts, as this is an internal only implementation.
1340             Contract.Assert(thisRef != null, "Expected a non-null thisRef");
1341             Contract.Assert(beginMethod != null, "Expected a non-null beginMethod");
1342             Contract.Assert(endMethod != null, "Expected a non-null endMethod");
1343
1344             // Create the promise and start the operation.
1345             // No try/catch is necessary here as we want exceptions to bubble out, and because
1346             // the task doesn't have AttachedToParent set on it, there's no need to complete it in
1347             // case of an exception occurring... we can just let it go unresolved.
1348             var promise = new FromAsyncTrimPromise<TInstance>(thisRef, endMethod);
1349             var asyncResult = beginMethod(thisRef, args, FromAsyncTrimPromise<TInstance>.s_completeFromAsyncResult, promise);
1350
1351             // If the IAsyncResult completed asynchronously, completing the promise will be handled by the callback.
1352             // If it completed synchronously, we'll handle that here.
1353             if (asyncResult != null && asyncResult.CompletedSynchronously)
1354             {
1355                 Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
1356                 promise.Complete(thisRef, endMethod, asyncResult, requiresSynchronization: false);
1357             }
1358
1359             // Return the promise
1360             return promise;
1361         }
1362
1363         /// <summary>
1364         /// A specialized task used by FromAsyncTrim.  Stores relevant information as instance
1365         /// state so that we can avoid unnecessary closure/delegate allocations.
1366         /// </summary>
1367         /// <typeparam name="TInstance">Specifies the type of the instance on which the APM implementation lives.</typeparam>
1368         private sealed class FromAsyncTrimPromise<TInstance> : Task<TResult> where TInstance : class
1369         {
1370             /// <summary>A cached delegate used as the callback for the BeginXx method.</summary>
1371             internal readonly static AsyncCallback s_completeFromAsyncResult = CompleteFromAsyncResult;
1372
1373             /// <summary>A reference to the object on which the begin/end methods are invoked.</summary>
1374             private TInstance m_thisRef;
1375             /// <summary>The end method.</summary>
1376             private Func<TInstance, IAsyncResult, TResult> m_endMethod;
1377
1378             /// <summary>Initializes the promise.</summary>
1379             /// <param name="thisRef">A reference to the object on which the begin/end methods are invoked.</param>
1380             /// <param name="endMethod">The end method.</param>
1381             internal FromAsyncTrimPromise(TInstance thisRef, Func<TInstance, IAsyncResult, TResult> endMethod) : base()
1382             {
1383                 Contract.Requires(thisRef != null, "Expected a non-null thisRef");
1384                 Contract.Requires(endMethod != null, "Expected a non-null endMethod");
1385                 m_thisRef = thisRef;
1386                 m_endMethod = endMethod;
1387             }
1388
1389             /// <summary>
1390             /// Completes the asynchronous operation using information in the IAsyncResult.  
1391             /// IAsyncResult.AsyncState neeeds to be the FromAsyncTrimPromise to complete.
1392             /// </summary>
1393             /// <param name="asyncResult">The IAsyncResult for the async operation.</param>
1394             internal static void CompleteFromAsyncResult(IAsyncResult asyncResult)
1395             {
1396                 // Validate argument
1397                 if (asyncResult == null) throw new ArgumentNullException("asyncResult");
1398                 Contract.EndContractBlock();
1399
1400                 var promise = asyncResult.AsyncState as FromAsyncTrimPromise<TInstance>;
1401                 if (promise == null) throw new ArgumentException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndCalledMultiple"), "asyncResult");
1402
1403                 // Grab the relevant state and then null it out so that the task doesn't hold onto the state unnecessarily
1404                 var thisRef = promise.m_thisRef;
1405                 var endMethod = promise.m_endMethod;
1406                 promise.m_thisRef = default(TInstance);
1407                 promise.m_endMethod = null;
1408                 if (endMethod == null) throw new ArgumentException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndCalledMultiple"), "asyncResult");
1409
1410                 // Complete the promise.  If the IAsyncResult completed synchronously,
1411                 // we'll instead complete the promise at the call site.
1412                 if (!asyncResult.CompletedSynchronously)
1413                 {
1414                     promise.Complete(thisRef, endMethod, asyncResult, requiresSynchronization:true);
1415                 }
1416             }
1417
1418             /// <summary>Completes the promise.</summary>
1419             /// <param name="requiresSynchronization">
1420             /// true if synchronization is needed to completed the task;
1421             /// false if the task may be completed without synchronization
1422             /// because it hasn't been handed out.
1423             /// </param>
1424             /// <param name="thisRef">The target instance on which the end method should be called.</param>
1425             /// <param name="endMethod">The end method to call to retrieve the result.</param>
1426             /// <param name="asyncResult">The IAsyncResult for the async operation.</param>
1427             /// <permission cref="requiresSynchronization">
1428             /// Whether completing the task requires synchronization.  This should be true
1429             /// unless absolutely sure that the task has not yet been handed out to any consumers.
1430             /// </permission>
1431             internal void Complete(
1432                 TInstance thisRef, Func<TInstance, IAsyncResult, TResult> endMethod, IAsyncResult asyncResult,
1433                 bool requiresSynchronization)
1434             {
1435                 Contract.Assert(!IsCompleted, "The task should not have been completed yet.");
1436
1437                 // Run the end method and complete the task
1438                 bool successfullySet = false;
1439                 try
1440                 {
1441                     var result = endMethod(thisRef, asyncResult);
1442                     if (requiresSynchronization)
1443                     {
1444                         successfullySet = TrySetResult(result);
1445                     }
1446                     else
1447                     {
1448                         // If requiresSynchronization is false, we can use the DangerousSetResult
1449                         // method, which uses no synchronization to complete the task.  This is
1450                         // only valid when the operation is completing synchronously such
1451                         // that the task has not yet been handed out to any consumers.
1452                         DangerousSetResult(result);
1453                         successfullySet = true;
1454                     }
1455                 }
1456                 catch (OperationCanceledException oce)
1457                 {
1458                     successfullySet = TrySetCanceled(oce.CancellationToken, oce);
1459                 }
1460                 catch (Exception exc)
1461                 {
1462                     successfullySet = TrySetException(exc);
1463                 }
1464                 Contract.Assert(successfullySet, "Expected the task to not yet be completed");
1465             }
1466         }
1467
1468         // Utility method to create a canceled future-style task.
1469         // Used by ContinueWhenAll/Any to bail out early on a pre-canceled token.
1470         private static Task<TResult> CreateCanceledTask(TaskContinuationOptions continuationOptions, CancellationToken ct)
1471         {
1472             TaskCreationOptions tco;
1473             InternalTaskOptions dontcare;
1474             Task.CreationOptionsFromContinuationOptions(continuationOptions, out tco, out dontcare);
1475             return new Task<TResult>(true, default(TResult), tco, ct);
1476         }
1477
1478         //
1479         // ContinueWhenAll() methods
1480         //
1481
1482         /// <summary>
1483         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> 
1484         /// that will be started upon the completion of a set of provided Tasks.
1485         /// </summary>
1486         /// <param name="tasks">The array of tasks from which to continue.</param>
1487         /// <param name="continuationFunction">The function delegate to execute when all tasks in 
1488         /// the <paramref name="tasks"/> array have completed.</param>
1489         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
1490         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the 
1491         /// <paramref name="tasks"/> array is null.</exception>
1492         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the 
1493         /// <paramref name="continuationFunction"/> argument is null.</exception>
1494         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the 
1495         /// <paramref name="tasks"/> array contains a null value.</exception>
1496         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the 
1497         /// <paramref name="tasks"/> array is empty.</exception>
1498         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
1499         public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction)
1500         {
1501             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1502             Contract.EndContractBlock();
1503
1504             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1505             return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
1506         }
1507
1508         /// <summary>
1509         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> 
1510         /// that will be started upon the completion of a set of provided Tasks.
1511         /// </summary>
1512         /// <param name="tasks">The array of tasks from which to continue.</param>
1513         /// <param name="continuationFunction">The function delegate to execute when all tasks in 
1514         /// the <paramref name="tasks"/> array have completed.</param>
1515         /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> 
1516         /// that will be assigned to the new continuation task.</param>
1517         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
1518         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the 
1519         /// <paramref name="tasks"/> array is null.</exception>
1520         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the 
1521         /// <paramref name="continuationFunction"/> argument is null.</exception>
1522         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the 
1523         /// <paramref name="tasks"/> array contains a null value.</exception>
1524         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the 
1525         /// <paramref name="tasks"/> array is empty.</exception>
1526         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
1527         /// has already been disposed.
1528         /// </exception>
1529         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
1530         public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction, CancellationToken cancellationToken)
1531         {
1532             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1533             Contract.EndContractBlock();
1534
1535             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1536             return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
1537         }
1538
1539         /// <summary>
1540         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
1541         /// that will be started upon the completion of a set of provided Tasks.
1542         /// </summary>
1543         /// <param name="tasks">The array of tasks from which to continue.</param>
1544         /// <param name="continuationFunction">The function delegate to execute when all tasks in the <paramref
1545         /// name="tasks"/> array have completed.</param>
1546         /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
1547         /// TaskContinuationOptions</see> value that controls the behavior of
1548         /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
1549         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
1550         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1551         /// <paramref name="tasks"/> array is null.</exception>
1552         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1553         /// <paramref name="continuationFunction"/> argument is null.</exception>
1554         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1555         /// <paramref name="tasks"/> array contains a null value.</exception>
1556         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1557         /// <paramref name="tasks"/> array is empty.</exception>
1558         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
1559         /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
1560         /// value.</exception>
1561         /// <remarks>
1562         /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, 
1563         /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation 
1564         /// will be executed, are illegal with ContinueWhenAll.
1565         /// </remarks>
1566         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
1567         public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction, TaskContinuationOptions continuationOptions)
1568         {
1569             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1570             Contract.EndContractBlock();
1571
1572             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1573             return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
1574         }
1575
1576         /// <summary>
1577         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
1578         /// that will be started upon the completion of a set of provided Tasks.
1579         /// </summary>
1580         /// <param name="tasks">The array of tasks from which to continue.</param>
1581         /// <param name="continuationFunction">The function delegate to execute when all tasks in the <paramref
1582         /// name="tasks"/> array have completed.</param>
1583         /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> 
1584         /// that will be assigned to the new continuation task.</param>
1585         /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
1586         /// TaskContinuationOptions</see> value that controls the behavior of
1587         /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
1588         /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
1589         /// that is used to schedule the created continuation <see
1590         /// cref="T:System.Threading.Tasks.Task">Task</see>.</param>
1591         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
1592         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1593         /// <paramref name="tasks"/> array is null.</exception>
1594         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1595         /// <paramref name="continuationFunction"/> argument is null.</exception>
1596         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1597         /// <paramref name="scheduler"/> argument is null.</exception>
1598         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1599         /// <paramref name="tasks"/> array contains a null value.</exception>
1600         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1601         /// <paramref name="tasks"/> array is empty.</exception>
1602         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
1603         /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
1604         /// value.</exception>
1605         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
1606         /// has already been disposed.
1607         /// </exception>
1608         /// <remarks>
1609         /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, 
1610         /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation 
1611         /// will be executed, are illegal with ContinueWhenAll.
1612         /// </remarks>
1613         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
1614         public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction,
1615             CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
1616         {
1617             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1618             Contract.EndContractBlock();
1619
1620             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1621             return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
1622         }
1623
1624         /// <summary>
1625         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
1626         /// that will be started upon the completion of a set of provided Tasks.
1627         /// </summary>
1628         /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
1629         /// <param name="tasks">The array of tasks from which to continue.</param>
1630         /// <param name="continuationFunction">The function delegate to execute when all tasks in the
1631         /// <paramref name="tasks"/> array have completed.</param>
1632         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
1633         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1634         /// <paramref name="tasks"/> array is null.</exception>
1635         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1636         /// <paramref name="continuationFunction"/> argument is null.</exception>
1637         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1638         /// <paramref name="tasks"/> array contains a null value.</exception>
1639         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1640         /// <paramref name="tasks"/> array is empty.</exception>
1641         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
1642         public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction)
1643         {
1644             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1645             Contract.EndContractBlock();
1646
1647             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1648             return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
1649         }
1650
1651         /// <summary>
1652         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
1653         /// that will be started upon the completion of a set of provided Tasks.
1654         /// </summary>
1655         /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
1656         /// <param name="tasks">The array of tasks from which to continue.</param>
1657         /// <param name="continuationFunction">The function delegate to execute when all tasks in the
1658         /// <paramref name="tasks"/> array have completed.</param>
1659         /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> 
1660         /// that will be assigned to the new continuation task.</param>
1661         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
1662         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1663         /// <paramref name="tasks"/> array is null.</exception>
1664         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1665         /// <paramref name="continuationFunction"/> argument is null.</exception>
1666         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1667         /// <paramref name="tasks"/> array contains a null value.</exception>
1668         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1669         /// <paramref name="tasks"/> array is empty.</exception>
1670         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
1671         /// has already been disposed.
1672         /// </exception>
1673         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
1674         public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
1675             CancellationToken cancellationToken)
1676         {
1677             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1678             Contract.EndContractBlock();
1679
1680             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1681             return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
1682         }
1683
1684         /// <summary>
1685         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
1686         /// that will be started upon the completion of a set of provided Tasks.
1687         /// </summary>
1688         /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
1689         /// <param name="tasks">The array of tasks from which to continue.</param>
1690         /// <param name="continuationFunction">The function delegate to execute when all tasks in the
1691         /// <paramref name="tasks"/> array have completed.</param>
1692         /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
1693         /// TaskContinuationOptions</see> value that controls the behavior of
1694         /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
1695         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
1696         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1697         /// <paramref name="tasks"/> array is null.</exception>
1698         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1699         /// <paramref name="continuationFunction"/> argument is null.</exception>
1700         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1701         /// <paramref name="tasks"/> array contains a null value.</exception>
1702         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1703         /// <paramref name="tasks"/> array is empty.</exception>
1704         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
1705         /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
1706         /// value.</exception>
1707         /// <remarks>
1708         /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, 
1709         /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation 
1710         /// will be executed, are illegal with ContinueWhenAll.
1711         /// </remarks>
1712         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
1713         public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
1714             TaskContinuationOptions continuationOptions)
1715         {
1716             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1717             Contract.EndContractBlock();
1718
1719             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1720             return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
1721         }
1722
1723         /// <summary>
1724         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
1725         /// that will be started upon the completion of a set of provided Tasks.
1726         /// </summary>
1727         /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
1728         /// <param name="tasks">The array of tasks from which to continue.</param>
1729         /// <param name="continuationFunction">The function delegate to execute when all tasks in the
1730         /// <paramref name="tasks"/> array have completed.</param>
1731         /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> 
1732         /// that will be assigned to the new continuation task.</param>
1733         /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
1734         /// TaskContinuationOptions</see> value that controls the behavior of
1735         /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
1736         /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
1737         /// that is used to schedule the created continuation <see
1738         /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
1739         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
1740         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1741         /// <paramref name="tasks"/> array is null.</exception>
1742         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1743         /// <paramref name="continuationFunction"/> argument is null.</exception>
1744         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1745         /// <paramref name="scheduler"/> argument is null.</exception>
1746         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1747         /// <paramref name="tasks"/> array contains a null value.</exception>
1748         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1749         /// <paramref name="tasks"/> array is empty.</exception>
1750         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
1751         /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
1752         /// value.</exception>
1753         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
1754         /// has already been disposed.
1755         /// </exception>
1756         /// <remarks>
1757         /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, 
1758         /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation 
1759         /// will be executed, are illegal with ContinueWhenAll.
1760         /// </remarks>
1761         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
1762         public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
1763             CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
1764         {
1765             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1766             Contract.EndContractBlock();
1767
1768             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1769             return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
1770         }
1771
1772    
1773         // Core implementation of ContinueWhenAll -- the generic version
1774         // Note: if you make any changes to this method, please do the same to the non-generic version too. 
1775         internal static Task<TResult> ContinueWhenAllImpl<TAntecedentResult>(Task<TAntecedentResult>[] tasks,
1776             Func<Task<TAntecedentResult>[], TResult> continuationFunction, Action<Task<TAntecedentResult>[]> continuationAction,
1777             TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler, ref StackCrawlMark stackMark)
1778         {
1779             // check arguments
1780             TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
1781             if (tasks == null) throw new ArgumentNullException("tasks");
1782             //ArgumentNullException of continuationFunction or continuationAction is checked by the caller
1783             Contract.Requires((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null");
1784             if (scheduler == null) throw new ArgumentNullException("scheduler");
1785             Contract.EndContractBlock();
1786
1787             // Check tasks array and make defensive copy
1788             Task<TAntecedentResult>[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy<TAntecedentResult>(tasks);
1789
1790             // Bail early if cancellation has been requested.
1791             if (cancellationToken.IsCancellationRequested
1792                 && ((continuationOptions & TaskContinuationOptions.LazyCancellation) == 0)
1793                 )
1794             {
1795                 return CreateCanceledTask(continuationOptions, cancellationToken);
1796             }
1797
1798             // Call common ContinueWhenAll() setup logic, extract starter task.
1799             var starter = TaskFactory.CommonCWAllLogic(tasksCopy);
1800
1801             // returned continuation task, off of starter
1802             if (continuationFunction != null)
1803             {
1804                 return starter.ContinueWith<TResult>(
1805                    // use a cached delegate
1806                    GenericDelegateCache<TAntecedentResult, TResult>.CWAllFuncDelegate,
1807                    continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
1808             }
1809             else
1810             {
1811                 Contract.Assert(continuationAction != null);
1812
1813                 return starter.ContinueWith<TResult>(
1814                    // use a cached delegate
1815                    GenericDelegateCache<TAntecedentResult, TResult>.CWAllActionDelegate,
1816                    continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
1817             }
1818         }
1819
1820         // Core implementation of ContinueWhenAll -- the non-generic version
1821         // Note: if you make any changes to this method, please do the same to the generic version too. 
1822         internal static Task<TResult> ContinueWhenAllImpl(Task[] tasks,
1823             Func<Task[], TResult> continuationFunction, Action<Task[]> continuationAction,
1824             TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler, ref StackCrawlMark stackMark)
1825         {
1826             // check arguments
1827             TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
1828             if (tasks == null) throw new ArgumentNullException("tasks");
1829             //ArgumentNullException of continuationFunction or continuationAction is checked by the caller
1830             Contract.Requires((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null");
1831             if (scheduler == null) throw new ArgumentNullException("scheduler");
1832             Contract.EndContractBlock();
1833
1834             // Check tasks array and make defensive copy
1835             Task[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy(tasks);
1836
1837             // Bail early if cancellation has been requested.
1838             if (cancellationToken.IsCancellationRequested
1839                 && ((continuationOptions & TaskContinuationOptions.LazyCancellation) == 0)
1840                 )
1841             {
1842                 return CreateCanceledTask(continuationOptions, cancellationToken);
1843             }
1844
1845             // Perform common ContinueWhenAll() setup logic, extract starter task
1846             var starter = TaskFactory.CommonCWAllLogic(tasksCopy);
1847
1848             // returned continuation task, off of starter
1849             if (continuationFunction != null)
1850             {
1851                 return starter.ContinueWith(
1852                     //the following delegate avoids closure capture as much as possible
1853                     //completedTasks.Result == tasksCopy;
1854                     //state == continuationFunction
1855                     (completedTasks, state) => 
1856                     {
1857                         completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
1858                         return ((Func<Task[], TResult>)state)(completedTasks.Result); 
1859                     },
1860                     continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
1861             }
1862             else
1863             {
1864                 Contract.Assert(continuationAction != null);
1865                 return starter.ContinueWith<TResult>(
1866                     //the following delegate avoids closure capture as much as possible
1867                     //completedTasks.Result == tasksCopy;
1868                     //state == continuationAction
1869                    (completedTasks, state) => 
1870                    {
1871                        completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
1872                        ((Action<Task[]>)state)(completedTasks.Result); return default(TResult); 
1873                    },
1874                    continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
1875             }
1876         }
1877
1878         //
1879         // ContinueWhenAny() methods
1880         //
1881
1882         /// <summary>
1883         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
1884         /// that will be started upon the completion of any Task in the provided set.
1885         /// </summary>
1886         /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
1887         /// <param name="continuationFunction">The function delegate to execute when one task in the <paramref
1888         /// name="tasks"/> array completes.</param>
1889         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
1890         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1891         /// <paramref name="tasks"/> array is null.</exception>
1892         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1893         /// <paramref name="continuationFunction"/> argument is null.</exception>
1894         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1895         /// <paramref name="tasks"/> array contains a null value.</exception>
1896         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1897         /// <paramref name="tasks"/> array is empty.</exception>
1898         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
1899         public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction)
1900         {
1901             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1902             Contract.EndContractBlock();
1903
1904             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1905             return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
1906         }
1907
1908         /// <summary>
1909         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
1910         /// that will be started upon the completion of any Task in the provided set.
1911         /// </summary>
1912         /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
1913         /// <param name="continuationFunction">The function delegate to execute when one task in the <paramref
1914         /// name="tasks"/> array completes.</param>
1915         /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> 
1916         /// that will be assigned to the new continuation task.</param>
1917         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
1918         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1919         /// <paramref name="tasks"/> array is null.</exception>
1920         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1921         /// <paramref name="continuationFunction"/> argument is null.</exception>
1922         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1923         /// <paramref name="tasks"/> array contains a null value.</exception>
1924         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1925         /// <paramref name="tasks"/> array is empty.</exception>
1926         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
1927         /// has already been disposed.
1928         /// </exception>
1929         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
1930         public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
1931         {
1932             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1933             Contract.EndContractBlock();
1934
1935             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1936             return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
1937         }
1938
1939         /// <summary>
1940         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
1941         /// that will be started upon the completion of any Task in the provided set.
1942         /// </summary>
1943         /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
1944         /// <param name="continuationFunction">The function delegate to execute when one task in the <paramref
1945         /// name="tasks"/> array completes.</param>
1946         /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
1947         /// TaskContinuationOptions</see> value that controls the behavior of
1948         /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
1949         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
1950         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1951         /// <paramref name="tasks"/> array is null.</exception>
1952         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1953         /// <paramref name="continuationFunction"/> argument is null.</exception>
1954         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1955         /// <paramref name="tasks"/> array contains a null value.</exception>
1956         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1957         /// <paramref name="tasks"/> array is empty.</exception>
1958         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
1959         /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
1960         /// value.</exception>
1961         /// <remarks>
1962         /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, 
1963         /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation 
1964         /// will be executed, are illegal with ContinueWhenAny.
1965         /// </remarks>
1966         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
1967         public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
1968         {
1969             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1970             Contract.EndContractBlock();
1971
1972             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1973             return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
1974         }
1975
1976         /// <summary>
1977         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
1978         /// that will be started upon the completion of any Task in the provided set.
1979         /// </summary>
1980         /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
1981         /// <param name="continuationFunction">The function delegate to execute when one task in the <paramref
1982         /// name="tasks"/> array completes.</param>
1983         /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> 
1984         /// that will be assigned to the new continuation task.</param>
1985         /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
1986         /// TaskContinuationOptions</see> value that controls the behavior of
1987         /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
1988         /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
1989         /// that is used to schedule the created continuation <see
1990         /// cref="T:System.Threading.Tasks.Task">Task</see>.</param>
1991         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
1992         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1993         /// <paramref name="tasks"/> array is null.</exception>
1994         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1995         /// <paramref name="continuationFunction"/> argument is null.</exception>
1996         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
1997         /// <paramref name="scheduler"/> argument is null.</exception>
1998         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
1999         /// <paramref name="tasks"/> array contains a null value.</exception>
2000         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
2001         /// <paramref name="tasks"/> array is empty.</exception>
2002         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
2003         /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
2004         /// value.</exception>
2005         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
2006         /// has already been disposed.
2007         /// </exception>
2008         /// <remarks>
2009         /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, 
2010         /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation 
2011         /// will be executed, are illegal with ContinueWhenAny.
2012         /// </remarks>
2013         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
2014         public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction,
2015             CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
2016         {
2017             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
2018             Contract.EndContractBlock();
2019
2020             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
2021             return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
2022         }
2023
2024         /// <summary>
2025         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
2026         /// that will be started upon the completion of any Task in the provided set.
2027         /// </summary>
2028         /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
2029         /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
2030         /// <param name="continuationFunction">The function delegate to execute when one task in the
2031         /// <paramref name="tasks"/> array completes.</param>
2032         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
2033         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
2034         /// <paramref name="tasks"/> array is null.</exception>
2035         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
2036         /// <paramref name="continuationFunction"/> argument is null.</exception>
2037         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
2038         /// <paramref name="tasks"/> array contains a null value.</exception>
2039         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
2040         /// <paramref name="tasks"/> array is empty.</exception>
2041         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
2042         public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction)
2043         {
2044             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
2045             Contract.EndContractBlock();
2046
2047             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
2048             return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
2049         }
2050
2051         /// <summary>
2052         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
2053         /// that will be started upon the completion of any Task in the provided set.
2054         /// </summary>
2055         /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
2056         /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
2057         /// <param name="continuationFunction">The function delegate to execute when one task in the
2058         /// <paramref name="tasks"/> array completes.</param>
2059         /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> 
2060         /// that will be assigned to the new continuation task.</param>
2061         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
2062         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
2063         /// <paramref name="tasks"/> array is null.</exception>
2064         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
2065         /// <paramref name="continuationFunction"/> argument is null.</exception>
2066         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
2067         /// <paramref name="tasks"/> array contains a null value.</exception>
2068         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
2069         /// <paramref name="tasks"/> array is empty.</exception>
2070         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
2071         /// has already been disposed.
2072         /// </exception>
2073         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
2074         public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
2075             CancellationToken cancellationToken)
2076         {
2077             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
2078             Contract.EndContractBlock();
2079
2080             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
2081             return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
2082         }
2083
2084         /// <summary>
2085         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
2086         /// that will be started upon the completion of any Task in the provided set.
2087         /// </summary>
2088         /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
2089         /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
2090         /// <param name="continuationFunction">The function delegate to execute when one task in the
2091         /// <paramref name="tasks"/> array completes.</param>
2092         /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
2093         /// TaskContinuationOptions</see> value that controls the behavior of
2094         /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
2095         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
2096         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
2097         /// <paramref name="tasks"/> array is null.</exception>
2098         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
2099         /// <paramref name="continuationFunction"/> argument is null.</exception>
2100         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
2101         /// <paramref name="tasks"/> array contains a null value.</exception>
2102         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
2103         /// <paramref name="tasks"/> array is empty.</exception>
2104         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
2105         /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
2106         /// value.</exception>
2107         /// <remarks>
2108         /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, 
2109         /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation 
2110         /// will be executed, are illegal with ContinueWhenAny.
2111         /// </remarks>
2112         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
2113         public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
2114             TaskContinuationOptions continuationOptions)
2115         {
2116             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
2117             Contract.EndContractBlock();
2118
2119             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
2120             return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
2121         }
2122
2123         /// <summary>
2124         /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
2125         /// that will be started upon the completion of any Task in the provided set.
2126         /// </summary>
2127         /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
2128         /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
2129         /// <param name="continuationFunction">The function delegate to execute when one task in the
2130         /// <paramref name="tasks"/> array completes.</param>
2131         /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> 
2132         /// that will be assigned to the new continuation task.</param>
2133         /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
2134         /// TaskContinuationOptions</see> value that controls the behavior of
2135         /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
2136         /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
2137         /// that is used to schedule the created continuation <see
2138         /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
2139         /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
2140         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
2141         /// <paramref name="tasks"/> array is null.</exception>
2142         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
2143         /// <paramref name="continuationFunction"/> argument is null.</exception>
2144         /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
2145         /// <paramref name="scheduler"/> argument is null.</exception>
2146         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
2147         /// <paramref name="tasks"/> array contains a null value.</exception>
2148         /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
2149         /// <paramref name="tasks"/> array is empty.</exception>
2150         /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
2151         /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
2152         /// value.</exception>
2153         /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
2154         /// has already been disposed.
2155         /// </exception>
2156         /// <remarks>
2157         /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, 
2158         /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation 
2159         /// will be executed, are illegal with ContinueWhenAny.
2160         /// </remarks>
2161         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable            
2162         public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
2163             CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
2164         {
2165             if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
2166             Contract.EndContractBlock();
2167
2168             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
2169             return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
2170         }
2171
2172         // Core implementation of ContinueWhenAny, non-generic version
2173         // Note: if you make any changes to this method, be sure to do the same to the generic version 
2174         internal static Task<TResult> ContinueWhenAnyImpl(Task[] tasks,
2175             Func<Task, TResult> continuationFunction, Action<Task> continuationAction,
2176             TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler, ref StackCrawlMark stackMark)
2177         {
2178             // check arguments
2179             TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
2180             if (tasks == null) throw new ArgumentNullException("tasks");
2181             if(tasks.Length == 0) throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), "tasks");
2182
2183             //ArgumentNullException of continuationFunction or continuationAction is checked by the caller
2184             Contract.Requires((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null");
2185             if (scheduler == null) throw new ArgumentNullException("scheduler");
2186             Contract.EndContractBlock();
2187
2188             // Call common ContinueWhenAny() setup logic, extract starter
2189             Task<Task> starter = TaskFactory.CommonCWAnyLogic(tasks);
2190
2191             // Bail early if cancellation has been requested.
2192             if (cancellationToken.IsCancellationRequested
2193                 && ((continuationOptions & TaskContinuationOptions.LazyCancellation) == 0)
2194                 )
2195             {
2196                 return CreateCanceledTask(continuationOptions, cancellationToken);
2197             }
2198
2199             // returned continuation task, off of starter
2200             if (continuationFunction != null)
2201             {
2202                 return starter.ContinueWith(
2203                     //the following delegate avoids closure capture as much as possible
2204                     //completedTask.Result is the winning task; state == continuationAction
2205                      (completedTask, state) => { return ((Func<Task, TResult>)state)(completedTask.Result); },
2206                      continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
2207             }
2208             else
2209             {
2210                 Contract.Assert(continuationAction != null);
2211                 return starter.ContinueWith<TResult>(
2212                     //the following delegate avoids closure capture as much as possible
2213                     //completedTask.Result is the winning task; state == continuationAction
2214                     (completedTask, state) => { ((Action<Task>)state)(completedTask.Result); return default(TResult); },
2215                     continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
2216             }
2217         }
2218
2219
2220         // Core implementation of ContinueWhenAny, generic version
2221         // Note: if you make any changes to this method, be sure to do the same to the non-generic version 
2222         internal static Task<TResult> ContinueWhenAnyImpl<TAntecedentResult>(Task<TAntecedentResult>[] tasks,
2223             Func<Task<TAntecedentResult>, TResult> continuationFunction, Action<Task<TAntecedentResult>> continuationAction,
2224             TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler, ref StackCrawlMark stackMark)
2225         {
2226             // check arguments
2227             TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
2228             if (tasks == null) throw new ArgumentNullException("tasks");
2229             if (tasks.Length == 0) throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), "tasks");
2230             //ArgumentNullException of continuationFunction or continuationAction is checked by the caller
2231             Contract.Requires((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null");
2232             if (scheduler == null) throw new ArgumentNullException("scheduler");
2233             Contract.EndContractBlock();
2234
2235             // Call common ContinueWhenAny setup logic, extract starter
2236             var starter = TaskFactory.CommonCWAnyLogic(tasks);
2237
2238             // Bail early if cancellation has been requested.
2239             if (cancellationToken.IsCancellationRequested
2240                 && ((continuationOptions & TaskContinuationOptions.LazyCancellation) == 0)
2241                 )
2242             {
2243                 return CreateCanceledTask(continuationOptions, cancellationToken);
2244             }
2245
2246             // returned continuation task, off of starter
2247             if (continuationFunction != null)
2248             {
2249                 return starter.ContinueWith<TResult>(
2250                     // Use a cached delegate
2251                     GenericDelegateCache<TAntecedentResult, TResult>.CWAnyFuncDelegate,
2252                     continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
2253             }
2254             else
2255             {
2256                 Contract.Assert(continuationAction != null);
2257                 return starter.ContinueWith<TResult>(
2258                     // Use a cached delegate
2259                     GenericDelegateCache<TAntecedentResult,TResult>.CWAnyActionDelegate,
2260                     continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
2261             }
2262         }
2263     }
2264
2265     // For the ContinueWhenAnyImpl/ContinueWhenAllImpl methods that are generic on TAntecedentResult,
2266     // the compiler won't cache the internal ContinueWith delegate because it is generic on both
2267     // TAntecedentResult and TResult.  The GenericDelegateCache serves as a cache for those delegates.
2268     internal static class GenericDelegateCache<TAntecedentResult, TResult>
2269     {
2270         // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(non-null continuationFunction)
2271         internal static Func<Task<Task>, object, TResult> CWAnyFuncDelegate =
2272             (Task<Task> wrappedWinner, object state) =>
2273             {
2274                 var func = (Func<Task<TAntecedentResult>, TResult>)state;
2275                 var arg = (Task<TAntecedentResult>)wrappedWinner.Result;
2276                 return func(arg);
2277             };
2278
2279         // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(non-null continuationAction)
2280         internal static Func<Task<Task>, object, TResult> CWAnyActionDelegate =
2281             (Task<Task> wrappedWinner, object state) =>
2282             {
2283                 var action = (Action<Task<TAntecedentResult>>)state;
2284                 var arg = (Task<TAntecedentResult>)wrappedWinner.Result;
2285                 action(arg);
2286                 return default(TResult);
2287             };
2288
2289         // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(non-null continuationFunction)
2290         internal static Func<Task<Task<TAntecedentResult>[]>, object, TResult> CWAllFuncDelegate =
2291             (Task<Task<TAntecedentResult>[]> wrappedAntecedents, object state) =>
2292             {
2293                 wrappedAntecedents.NotifyDebuggerOfWaitCompletionIfNecessary();
2294                 var func = (Func<Task<TAntecedentResult>[], TResult>)state;
2295                 return func(wrappedAntecedents.Result);
2296             };
2297
2298         // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(non-null continuationAction)
2299         internal static Func<Task<Task<TAntecedentResult>[]>, object, TResult> CWAllActionDelegate =
2300             (Task<Task<TAntecedentResult>[]> wrappedAntecedents, object state) =>
2301             {
2302                 wrappedAntecedents.NotifyDebuggerOfWaitCompletionIfNecessary();
2303                 var action = (Action<Task<TAntecedentResult>[]>)state;
2304                 action(wrappedAntecedents.Result);
2305                 return default(TResult);
2306             };
2307
2308     }
2309
2310 }