3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
10 // <OWNER>Microsoft</OWNER>
12 // As with TaskFactory, TaskFactory<TResult> encodes common factory patterns into helper methods.
14 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
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;
24 namespace System.Threading.Tasks
27 /// Provides support for creating and scheduling
28 /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task{TResult}</see> objects.
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>
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.
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.
44 [HostProtection(Synchronization = true, ExternalThreading = true)]
45 public class TaskFactory<TResult>
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?
52 private CancellationToken m_defaultCancellationToken;
53 private TaskScheduler m_defaultScheduler;
54 private TaskCreationOptions m_defaultCreationOptions;
55 private TaskContinuationOptions m_defaultContinuationOptions;
57 private TaskScheduler DefaultScheduler
61 if (m_defaultScheduler == null) return TaskScheduler.Current;
62 else return m_defaultScheduler;
66 // sister method to above property -- avoids a TLS lookup
67 private TaskScheduler GetDefaultScheduler(Task currTask)
69 if (m_defaultScheduler != null) return m_defaultScheduler;
70 else if ((currTask != null)
71 && ((currTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
73 return currTask.ExecutingTaskScheduler;
74 else return TaskScheduler.Default;
80 /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the default configuration.
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>).
93 : this(default(CancellationToken), TaskCreationOptions.None, TaskContinuationOptions.None, null)
98 /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the default configuration.
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>
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>).
113 public TaskFactory(CancellationToken cancellationToken)
114 : this(cancellationToken, TaskCreationOptions.None, TaskContinuationOptions.None, null)
119 /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the specified configuration.
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.
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>).
137 public TaskFactory(TaskScheduler scheduler) // null means to use TaskScheduler.Current
138 : this(default(CancellationToken), TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
143 /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the specified configuration.
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}.
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}.
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.
159 /// With this constructor, the
160 /// <see cref="TaskCreationOptions"/> property is initialized to <paramref name="creationOptions"/>,
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>).
168 public TaskFactory(TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions)
169 : this(default(CancellationToken), creationOptions, continuationOptions, null)
174 /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the specified configuration.
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}.
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}.
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.
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.
198 /// With this constructor, the
199 /// <see cref="TaskCreationOptions"/> property is initialized to <paramref name="creationOptions"/>,
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>).
208 public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
210 TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
211 TaskFactory.CheckCreationOptions(creationOptions);
213 m_defaultCancellationToken = cancellationToken;
214 m_defaultScheduler = scheduler;
215 m_defaultCreationOptions = creationOptions;
216 m_defaultContinuationOptions = continuationOptions;
222 /// Gets the default <see cref="System.Threading.CancellationToken">CancellationToken</see> of this
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.
230 public CancellationToken CancellationToken { get { return m_defaultCancellationToken; } }
233 /// Gets the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> of this
234 /// TaskFactory{TResult}.
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>
242 public TaskScheduler Scheduler { get { return m_defaultScheduler; } }
245 /// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions
246 /// </see> value of this TaskFactory{TResult}.
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.
252 public TaskCreationOptions CreationOptions { get { return m_defaultCreationOptions; } }
255 /// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskContinuationOptions
256 /// </see> value of this TaskFactory{TResult}.
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.
262 public TaskContinuationOptions ContinuationOptions { get { return m_defaultContinuationOptions; } }
268 /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
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>
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.
283 [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
284 public Task<TResult> StartNew(Func<TResult> function)
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);
293 /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
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.
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.
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)
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);
322 /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
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
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>
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.
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)
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);
353 /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
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
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.
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.
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)
388 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
389 return Task<TResult>.StartNew(
390 Task.InternalCurrentIfAttached(creationOptions), function, cancellationToken,
391 creationOptions, InternalTaskOptions.None, scheduler, ref stackMark);
395 /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
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>
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.
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)
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);
422 /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
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.
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.
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)
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);
453 /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
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
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>
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.
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)
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);
486 /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
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
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.
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.
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)
523 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
524 return Task<TResult>.StartNew(Task.InternalCurrentIfAttached(creationOptions), function, state, cancellationToken,
525 creationOptions, InternalTaskOptions.None, scheduler, ref stackMark);
529 // APM Factory methods
532 // Common core logic for FromAsync calls. This minimizes the chance of "drift" between overload implementations.
533 private static void FromAsyncCoreLogic(
535 Func<IAsyncResult, TResult> endFunction,
536 Action<IAsyncResult> endAction,
537 Task<TResult> promise,
538 bool requiresSynchronization)
540 Contract.Requires((endFunction != null) != (endAction != null), "Expected exactly one of endFunction/endAction to be non-null");
543 OperationCanceledException oce = null;
544 TResult result = default(TResult);
548 if (endFunction != null)
550 result = endFunction(iar);
557 catch (OperationCanceledException _oce) { oce = _oce; }
558 catch (Exception e) { ex = e; }
563 promise.TrySetCanceled(oce.CancellationToken, oce);
567 bool bWonSetException = promise.TrySetException(ex);
568 if (bWonSetException && ex is ThreadAbortException)
570 promise.m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false);
575 if (AsyncCausalityTracer.LoggingOn)
576 AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Completed);
578 if (Task.s_asyncDebuggingEnabled)
580 Task.RemoveFromActiveTasks(promise.Id);
582 if (requiresSynchronization)
584 promise.TrySetResult(result);
588 promise.DangerousSetResult(result);
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.
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)
613 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
614 return FromAsyncImpl(asyncResult, endMethod, null, m_defaultCreationOptions, DefaultScheduler, ref stackMark);
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.
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)
642 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
643 return FromAsyncImpl(asyncResult, endMethod, null, creationOptions, DefaultScheduler, ref stackMark);
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.
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)
678 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
679 return FromAsyncImpl(asyncResult, endMethod, null, creationOptions, scheduler, ref stackMark);
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)
693 if (asyncResult == null)
694 throw new ArgumentNullException("asyncResult");
696 if (endFunction == null && endAction == null)
697 throw new ArgumentNullException("endMethod");
699 Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
701 if (scheduler == null)
702 throw new ArgumentNullException("scheduler");
703 Contract.EndContractBlock();
705 TaskFactory.CheckFromAsyncOptions(creationOptions, false);
707 Task<TResult> promise = new Task<TResult>((object)null, creationOptions);
709 if (AsyncCausalityTracer.LoggingOn)
710 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync", 0);
712 if (Task.s_asyncDebuggingEnabled)
714 Task.AddToActiveTasks(promise);
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
722 FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization:true);
725 default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null, ref stackMark);
727 if (AsyncCausalityTracer.LoggingOn)
728 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Verbose, t.Id, "TaskFactory.FromAsync Callback", 0);
730 if (Task.s_asyncDebuggingEnabled)
732 Task.AddToActiveTasks(t);
735 if (asyncResult.IsCompleted)
737 try { t.InternalRunSynchronously(scheduler, waitForCompletion:false); }
738 catch (Exception e) { promise.TrySetException(e); } // catch and log any scheduler exceptions
742 ThreadPool.RegisterWaitForSingleObject(
743 asyncResult.AsyncWaitHandle,
746 try { t.InternalRunSynchronously(scheduler, waitForCompletion: false); }
747 catch (Exception e) { promise.TrySetException(e); } // catch and log any scheduler exceptions
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.
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>
772 /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
774 public Task<TResult> FromAsync(
775 Func<AsyncCallback, object, IAsyncResult> beginMethod,
776 Func<IAsyncResult, TResult> endMethod, object state)
778 return FromAsyncImpl(beginMethod, endMethod, null, state, m_defaultCreationOptions);
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.
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>
801 /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
803 public Task<TResult> FromAsync(
804 Func<AsyncCallback, object, IAsyncResult> beginMethod,
805 Func<IAsyncResult, TResult> endMethod, object state, TaskCreationOptions creationOptions)
807 return FromAsyncImpl(beginMethod, endMethod, null, state, creationOptions);
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)
816 if (beginMethod == null)
817 throw new ArgumentNullException("beginMethod");
819 if (endFunction == null && endAction == null)
820 throw new ArgumentNullException("endMethod");
822 Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
824 TaskFactory.CheckFromAsyncOptions(creationOptions, true);
826 Task<TResult> promise = new Task<TResult>(state, creationOptions);
828 if (AsyncCausalityTracer.LoggingOn)
829 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync: " + beginMethod.Method.Name, 0);
831 if (Task.s_asyncDebuggingEnabled)
833 Task.AddToActiveTasks(promise);
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)
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 =>
849 if (invoked.TryRelaxedSet ())
850 FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
852 if (asyncResult != null && asyncResult.CompletedSynchronously && invoked.TryRelaxedSet ())
854 Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
855 FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false);
860 //This is the original 4.0 behaviour
861 var asyncResult = beginMethod(iar =>
863 FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
869 if (AsyncCausalityTracer.LoggingOn)
870 AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Error);
872 if (Task.s_asyncDebuggingEnabled)
874 Task.RemoveFromActiveTasks(promise.Id);
877 // Make sure we don't leave promise "dangling".
878 promise.TrySetResult(default(TResult));
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.
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>
904 /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
906 public Task<TResult> FromAsync<TArg1>(
907 Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
908 Func<IAsyncResult, TResult> endMethod,
909 TArg1 arg1, object state)
911 return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, m_defaultCreationOptions);
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.
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>
938 /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
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)
945 return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, creationOptions);
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)
954 if (beginMethod == null)
955 throw new ArgumentNullException("beginMethod");
957 if (endFunction == null && endAction == null)
958 throw new ArgumentNullException("endFunction");
960 Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
962 TaskFactory.CheckFromAsyncOptions(creationOptions, true);
964 Task<TResult> promise = new Task<TResult>(state, creationOptions);
966 if (AsyncCausalityTracer.LoggingOn)
967 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync: " + beginMethod.Method.Name, 0);
969 if (Task.s_asyncDebuggingEnabled)
971 Task.AddToActiveTasks(promise);
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)
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 =>
986 if (invoked.TryRelaxedSet ())
987 FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
989 if (asyncResult != null && asyncResult.CompletedSynchronously && invoked.TryRelaxedSet ())
991 Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
992 FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false);
997 //quirk for previous versions
998 var asyncResult = beginMethod(arg1, iar =>
1000 FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
1007 if (AsyncCausalityTracer.LoggingOn)
1008 AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Error);
1010 if (Task.s_asyncDebuggingEnabled)
1012 Task.RemoveFromActiveTasks(promise.Id);
1015 // Make sure we don't leave promise "dangling".
1016 promise.TrySetResult(default(TResult));
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.
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>
1046 /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
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)
1053 return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, m_defaultCreationOptions);
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.
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>
1084 /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
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)
1091 return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, creationOptions);
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)
1100 if (beginMethod == null)
1101 throw new ArgumentNullException("beginMethod");
1103 if (endFunction == null && endAction == null)
1104 throw new ArgumentNullException("endMethod");
1106 Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
1108 TaskFactory.CheckFromAsyncOptions(creationOptions, true);
1110 Task<TResult> promise = new Task<TResult>(state, creationOptions);
1112 if (AsyncCausalityTracer.LoggingOn)
1113 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync: " + beginMethod.Method.Name, 0);
1115 if (Task.s_asyncDebuggingEnabled)
1117 Task.AddToActiveTasks(promise);
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)
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 =>
1132 if (invoked.TryRelaxedSet ())
1133 FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
1135 if (asyncResult != null && asyncResult.CompletedSynchronously && invoked.TryRelaxedSet ())
1137 Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
1138 FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false);
1143 //quirk for previous versions
1144 var asyncResult = beginMethod(arg1, arg2, iar =>
1146 FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
1152 if (AsyncCausalityTracer.LoggingOn)
1153 AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Error);
1155 if (Task.s_asyncDebuggingEnabled)
1157 Task.RemoveFromActiveTasks(promise.Id);
1160 // Make sure we don't leave promise "dangling".
1161 promise.TrySetResult(default(TResult));
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.
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>
1195 /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
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)
1202 return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, m_defaultCreationOptions);
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.
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>
1237 /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
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)
1244 return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, creationOptions);
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)
1253 if (beginMethod == null)
1254 throw new ArgumentNullException("beginMethod");
1256 if (endFunction == null && endAction == null)
1257 throw new ArgumentNullException("endMethod");
1259 Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
1261 TaskFactory.CheckFromAsyncOptions(creationOptions, true);
1263 Task<TResult> promise = new Task<TResult>(state, creationOptions);
1265 if (AsyncCausalityTracer.LoggingOn)
1266 AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync: " + beginMethod.Method.Name, 0);
1268 if (Task.s_asyncDebuggingEnabled)
1270 Task.AddToActiveTasks(promise);
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)
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 =>
1285 if (invoked.TryRelaxedSet ())
1286 FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
1288 if (asyncResult != null && asyncResult.CompletedSynchronously && invoked.TryRelaxedSet ())
1290 Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
1291 FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false);
1296 //quirk for previous versions
1297 var asyncResult = beginMethod(arg1, arg2, arg3, iar =>
1299 FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
1305 if (AsyncCausalityTracer.LoggingOn)
1306 AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Error);
1308 if (Task.s_asyncDebuggingEnabled)
1310 Task.RemoveFromActiveTasks(promise.Id);
1313 // Make sure we don't leave the promise "dangling".
1314 promise.TrySetResult(default(TResult));
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.
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
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");
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);
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)
1355 Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
1356 promise.Complete(thisRef, endMethod, asyncResult, requiresSynchronization: false);
1359 // Return the promise
1364 /// A specialized task used by FromAsyncTrim. Stores relevant information as instance
1365 /// state so that we can avoid unnecessary closure/delegate allocations.
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
1370 /// <summary>A cached delegate used as the callback for the BeginXx method.</summary>
1371 internal readonly static AsyncCallback s_completeFromAsyncResult = CompleteFromAsyncResult;
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;
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()
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;
1390 /// Completes the asynchronous operation using information in the IAsyncResult.
1391 /// IAsyncResult.AsyncState neeeds to be the FromAsyncTrimPromise to complete.
1393 /// <param name="asyncResult">The IAsyncResult for the async operation.</param>
1394 internal static void CompleteFromAsyncResult(IAsyncResult asyncResult)
1396 // Validate argument
1397 if (asyncResult == null) throw new ArgumentNullException("asyncResult");
1398 Contract.EndContractBlock();
1400 var promise = asyncResult.AsyncState as FromAsyncTrimPromise<TInstance>;
1401 if (promise == null) throw new ArgumentException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndCalledMultiple"), "asyncResult");
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");
1410 // Complete the promise. If the IAsyncResult completed synchronously,
1411 // we'll instead complete the promise at the call site.
1412 if (!asyncResult.CompletedSynchronously)
1414 promise.Complete(thisRef, endMethod, asyncResult, requiresSynchronization:true);
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.
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.
1431 internal void Complete(
1432 TInstance thisRef, Func<TInstance, IAsyncResult, TResult> endMethod, IAsyncResult asyncResult,
1433 bool requiresSynchronization)
1435 Contract.Assert(!IsCompleted, "The task should not have been completed yet.");
1437 // Run the end method and complete the task
1438 bool successfullySet = false;
1441 var result = endMethod(thisRef, asyncResult);
1442 if (requiresSynchronization)
1444 successfullySet = TrySetResult(result);
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;
1456 catch (OperationCanceledException oce)
1458 successfullySet = TrySetCanceled(oce.CancellationToken, oce);
1460 catch (Exception exc)
1462 successfullySet = TrySetException(exc);
1464 Contract.Assert(successfullySet, "Expected the task to not yet be completed");
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)
1472 TaskCreationOptions tco;
1473 InternalTaskOptions dontcare;
1474 Task.CreationOptionsFromContinuationOptions(continuationOptions, out tco, out dontcare);
1475 return new Task<TResult>(true, default(TResult), tco, ct);
1479 // ContinueWhenAll() methods
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.
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)
1501 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1502 Contract.EndContractBlock();
1504 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1505 return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
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.
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.
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)
1532 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1533 Contract.EndContractBlock();
1535 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1536 return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
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.
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>
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.
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)
1569 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1570 Contract.EndContractBlock();
1572 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1573 return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
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.
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.
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.
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)
1617 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1618 Contract.EndContractBlock();
1620 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1621 return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
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.
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)
1644 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1645 Contract.EndContractBlock();
1647 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1648 return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
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.
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.
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)
1677 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1678 Contract.EndContractBlock();
1680 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1681 return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
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.
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>
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.
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)
1716 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1717 Contract.EndContractBlock();
1719 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1720 return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
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.
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.
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.
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)
1765 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1766 Contract.EndContractBlock();
1768 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1769 return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
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)
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();
1787 // Check tasks array and make defensive copy
1788 Task<TAntecedentResult>[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy<TAntecedentResult>(tasks);
1790 // Bail early if cancellation has been requested.
1791 if (cancellationToken.IsCancellationRequested
1792 && ((continuationOptions & TaskContinuationOptions.LazyCancellation) == 0)
1795 return CreateCanceledTask(continuationOptions, cancellationToken);
1798 // Call common ContinueWhenAll() setup logic, extract starter task.
1799 var starter = TaskFactory.CommonCWAllLogic(tasksCopy);
1801 // returned continuation task, off of starter
1802 if (continuationFunction != null)
1804 return starter.ContinueWith<TResult>(
1805 // use a cached delegate
1806 GenericDelegateCache<TAntecedentResult, TResult>.CWAllFuncDelegate,
1807 continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
1811 Contract.Assert(continuationAction != null);
1813 return starter.ContinueWith<TResult>(
1814 // use a cached delegate
1815 GenericDelegateCache<TAntecedentResult, TResult>.CWAllActionDelegate,
1816 continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
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)
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();
1834 // Check tasks array and make defensive copy
1835 Task[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy(tasks);
1837 // Bail early if cancellation has been requested.
1838 if (cancellationToken.IsCancellationRequested
1839 && ((continuationOptions & TaskContinuationOptions.LazyCancellation) == 0)
1842 return CreateCanceledTask(continuationOptions, cancellationToken);
1845 // Perform common ContinueWhenAll() setup logic, extract starter task
1846 var starter = TaskFactory.CommonCWAllLogic(tasksCopy);
1848 // returned continuation task, off of starter
1849 if (continuationFunction != null)
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) =>
1857 completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
1858 return ((Func<Task[], TResult>)state)(completedTasks.Result);
1860 continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
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) =>
1871 completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
1872 ((Action<Task[]>)state)(completedTasks.Result); return default(TResult);
1874 continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
1879 // ContinueWhenAny() methods
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.
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)
1901 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1902 Contract.EndContractBlock();
1904 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1905 return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
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.
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.
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)
1932 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1933 Contract.EndContractBlock();
1935 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1936 return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
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.
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>
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.
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)
1969 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
1970 Contract.EndContractBlock();
1972 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
1973 return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
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.
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.
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.
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)
2017 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
2018 Contract.EndContractBlock();
2020 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
2021 return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
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.
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)
2044 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
2045 Contract.EndContractBlock();
2047 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
2048 return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
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.
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.
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)
2077 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
2078 Contract.EndContractBlock();
2080 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
2081 return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
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.
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>
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.
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)
2116 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
2117 Contract.EndContractBlock();
2119 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
2120 return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
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.
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.
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.
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)
2165 if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
2166 Contract.EndContractBlock();
2168 StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
2169 return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
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)
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");
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();
2188 // Call common ContinueWhenAny() setup logic, extract starter
2189 Task<Task> starter = TaskFactory.CommonCWAnyLogic(tasks);
2191 // Bail early if cancellation has been requested.
2192 if (cancellationToken.IsCancellationRequested
2193 && ((continuationOptions & TaskContinuationOptions.LazyCancellation) == 0)
2196 return CreateCanceledTask(continuationOptions, cancellationToken);
2199 // returned continuation task, off of starter
2200 if (continuationFunction != null)
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);
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);
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)
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();
2235 // Call common ContinueWhenAny setup logic, extract starter
2236 var starter = TaskFactory.CommonCWAnyLogic(tasks);
2238 // Bail early if cancellation has been requested.
2239 if (cancellationToken.IsCancellationRequested
2240 && ((continuationOptions & TaskContinuationOptions.LazyCancellation) == 0)
2243 return CreateCanceledTask(continuationOptions, cancellationToken);
2246 // returned continuation task, off of starter
2247 if (continuationFunction != null)
2249 return starter.ContinueWith<TResult>(
2250 // Use a cached delegate
2251 GenericDelegateCache<TAntecedentResult, TResult>.CWAnyFuncDelegate,
2252 continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
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);
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>
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) =>
2274 var func = (Func<Task<TAntecedentResult>, TResult>)state;
2275 var arg = (Task<TAntecedentResult>)wrappedWinner.Result;
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) =>
2283 var action = (Action<Task<TAntecedentResult>>)state;
2284 var arg = (Task<TAntecedentResult>)wrappedWinner.Result;
2286 return default(TResult);
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) =>
2293 wrappedAntecedents.NotifyDebuggerOfWaitCompletionIfNecessary();
2294 var func = (Func<Task<TAntecedentResult>[], TResult>)state;
2295 return func(wrappedAntecedents.Result);
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) =>
2302 wrappedAntecedents.NotifyDebuggerOfWaitCompletionIfNecessary();
2303 var action = (Action<Task<TAntecedentResult>[]>)state;
2304 action(wrappedAntecedents.Result);
2305 return default(TResult);