1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
9 // A task that produces a value.
11 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
13 using System
.Diagnostics
;
14 using System
.Diagnostics
.CodeAnalysis
;
15 using System
.Runtime
.CompilerServices
;
17 namespace System
.Threading
.Tasks
20 /// Represents an asynchronous operation that produces a result at some time in the future.
22 /// <typeparam name="TResult">
23 /// The type of the result produced by this <see cref="Task{TResult}"/>.
27 /// <see cref="Task{TResult}"/> instances may be created in a variety of ways. The most common approach is by
28 /// using the task's <see cref="Factory"/> property to retrieve a <see
29 /// cref="System.Threading.Tasks.TaskFactory{TResult}"/> instance that can be used to create tasks for several
30 /// purposes. For example, to create a <see cref="Task{TResult}"/> that runs a function, the factory's StartNew
31 /// method may be used:
34 /// var t = Task<int>.Factory.StartNew(() => GenerateResult());
36 /// var t = Task.Factory.StartNew(() => GenerateResult());
39 /// Dim t = Task<int>.Factory.StartNew(Function() GenerateResult())
41 /// Dim t = Task.Factory.StartNew(Function() GenerateResult())
45 /// The <see cref="Task{TResult}"/> class also provides constructors that initialize the task but that do not
46 /// schedule it for execution. For performance reasons, the StartNew method should be the
47 /// preferred mechanism for creating and scheduling computational tasks, but for scenarios where creation
48 /// and scheduling must be separated, the constructors may be used, and the task's
49 /// <see cref="System.Threading.Tasks.Task.Start()">Start</see>
50 /// method may then be used to schedule the task for execution at a later time.
53 /// All members of <see cref="Task{TResult}"/>, except for
54 /// <see cref="System.Threading.Tasks.Task.Dispose()">Dispose</see>, are thread-safe
55 /// and may be used from multiple threads concurrently.
58 [DebuggerTypeProxy(typeof(SystemThreadingTasks_FutureDebugView
<>))]
59 [DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}, Result = {DebuggerDisplayResultDescription}")]
60 public class Task
<TResult
> : Task
62 // The value itself, if set.
63 [MaybeNull
] internal TResult m_result
= default!;
65 private static readonly TaskFactory
<TResult
> s_Factory
= new TaskFactory
<TResult
>();
67 // Extract rarely used helper for a static method in a separate type so that the Func<Task<Task>, Task<TResult>>
68 // generic instantiations don't contribute to all Task instantiations, but only those where WhenAny is used.
69 internal static class TaskWhenAnyCast
72 // public static Task<Task<TResult>> WhenAny<TResult>(IEnumerable<Task<TResult>> tasks);
73 // public static Task<Task<TResult>> WhenAny<TResult>(params Task<TResult>[] tasks);
74 // Used to "cast" from Task<Task> to Task<Task<TResult>>.
75 internal static readonly Func
<Task
<Task
>, Task
<TResult
>> Value
= completed
=> (Task
<TResult
>)completed
.Result
;
78 // Construct a promise-style task without any options.
84 // Construct a promise-style task with state and options.
85 internal Task(object? state
, TaskCreationOptions options
) :
86 base(state
, options
, promiseStyle
: true)
91 // Construct a pre-completed Task<TResult>
92 internal Task(TResult result
) :
93 base(false, TaskCreationOptions
.None
, default)
98 internal Task(bool canceled
, [AllowNull
] TResult result
, TaskCreationOptions creationOptions
, CancellationToken ct
)
99 : base(canceled
, creationOptions
, ct
)
108 /// Initializes a new <see cref="Task{TResult}"/> with the specified function.
110 /// <param name="function">
111 /// The delegate that represents the code to execute in the task. When the function has completed,
112 /// the task's <see cref="Result"/> property will be set to return the result value of the function.
114 /// <exception cref="System.ArgumentException">
115 /// The <paramref name="function"/> argument is null.
117 public Task(Func
<TResult
> function
)
118 : this(function
, null, default,
119 TaskCreationOptions
.None
, InternalTaskOptions
.None
, null)
125 /// Initializes a new <see cref="Task{TResult}"/> with the specified function.
127 /// <param name="function">
128 /// The delegate that represents the code to execute in the task. When the function has completed,
129 /// the task's <see cref="Result"/> property will be set to return the result value of the function.
131 /// <param name="cancellationToken">The <see cref="CancellationToken"/> to be assigned to this task.</param>
132 /// <exception cref="System.ArgumentException">
133 /// The <paramref name="function"/> argument is null.
135 /// <exception cref="System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
136 /// has already been disposed.
138 public Task(Func
<TResult
> function
, CancellationToken cancellationToken
)
139 : this(function
, null, cancellationToken
,
140 TaskCreationOptions
.None
, InternalTaskOptions
.None
, null)
145 /// Initializes a new <see cref="Task{TResult}"/> with the specified function and creation options.
147 /// <param name="function">
148 /// The delegate that represents the code to execute in the task. When the function has completed,
149 /// the task's <see cref="Result"/> property will be set to return the result value of the function.
151 /// <param name="creationOptions">
152 /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
153 /// customize the task's behavior.
155 /// <exception cref="System.ArgumentException">
156 /// The <paramref name="function"/> argument is null.
158 /// <exception cref="System.ArgumentOutOfRangeException">
159 /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
160 /// cref="System.Threading.Tasks.TaskCreationOptions"/>.
162 public Task(Func
<TResult
> function
, TaskCreationOptions creationOptions
)
163 : this(function
, Task
.InternalCurrentIfAttached(creationOptions
), default, creationOptions
, InternalTaskOptions
.None
, null)
168 /// Initializes a new <see cref="Task{TResult}"/> with the specified function and creation options.
170 /// <param name="function">
171 /// The delegate that represents the code to execute in the task. When the function has completed,
172 /// the task's <see cref="Result"/> property will be set to return the result value of the function.
174 /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
175 /// <param name="creationOptions">
176 /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
177 /// customize the task's behavior.
179 /// <exception cref="System.ArgumentException">
180 /// The <paramref name="function"/> argument is null.
182 /// <exception cref="System.ArgumentOutOfRangeException">
183 /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
184 /// cref="System.Threading.Tasks.TaskCreationOptions"/>.
186 /// <exception cref="System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
187 /// has already been disposed.
189 public Task(Func
<TResult
> function
, CancellationToken cancellationToken
, TaskCreationOptions creationOptions
)
190 : this(function
, Task
.InternalCurrentIfAttached(creationOptions
), cancellationToken
, creationOptions
, InternalTaskOptions
.None
, null)
195 /// Initializes a new <see cref="Task{TResult}"/> with the specified function and state.
197 /// <param name="function">
198 /// The delegate that represents the code to execute in the task. When the function has completed,
199 /// the task's <see cref="Result"/> property will be set to return the result value of the function.
201 /// <param name="state">An object representing data to be used by the action.</param>
202 /// <exception cref="System.ArgumentException">
203 /// The <paramref name="function"/> argument is null.
205 public Task(Func
<object?, TResult
> function
, object? state
)
206 : this(function
, state
, null, default,
207 TaskCreationOptions
.None
, InternalTaskOptions
.None
, null)
212 /// Initializes a new <see cref="Task{TResult}"/> with the specified action, state, and options.
214 /// <param name="function">
215 /// The delegate that represents the code to execute in the task. When the function has completed,
216 /// the task's <see cref="Result"/> property will be set to return the result value of the function.
218 /// <param name="state">An object representing data to be used by the function.</param>
219 /// <param name="cancellationToken">The <see cref="CancellationToken"/> to be assigned to the new task.</param>
220 /// <exception cref="System.ArgumentException">
221 /// The <paramref name="function"/> argument is null.
223 /// <exception cref="System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
224 /// has already been disposed.
226 public Task(Func
<object?, TResult
> function
, object? state
, CancellationToken cancellationToken
)
227 : this(function
, state
, null, cancellationToken
,
228 TaskCreationOptions
.None
, InternalTaskOptions
.None
, null)
233 /// Initializes a new <see cref="Task{TResult}"/> with the specified action, state, and options.
235 /// <param name="function">
236 /// The delegate that represents the code to execute in the task. When the function has completed,
237 /// the task's <see cref="Result"/> property will be set to return the result value of the function.
239 /// <param name="state">An object representing data to be used by the function.</param>
240 /// <param name="creationOptions">
241 /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
242 /// customize the task's behavior.
244 /// <exception cref="System.ArgumentException">
245 /// The <paramref name="function"/> argument is null.
247 /// <exception cref="System.ArgumentOutOfRangeException">
248 /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
249 /// cref="System.Threading.Tasks.TaskCreationOptions"/>.
251 public Task(Func
<object?, TResult
> function
, object? state
, TaskCreationOptions creationOptions
)
252 : this(function
, state
, Task
.InternalCurrentIfAttached(creationOptions
), default,
253 creationOptions
, InternalTaskOptions
.None
, null)
259 /// Initializes a new <see cref="Task{TResult}"/> with the specified action, state, and options.
261 /// <param name="function">
262 /// The delegate that represents the code to execute in the task. When the function has completed,
263 /// the task's <see cref="Result"/> property will be set to return the result value of the function.
265 /// <param name="state">An object representing data to be used by the function.</param>
266 /// <param name="cancellationToken">The <see cref="CancellationToken"/> to be assigned to the new task.</param>
267 /// <param name="creationOptions">
268 /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
269 /// customize the task's behavior.
271 /// <exception cref="System.ArgumentException">
272 /// The <paramref name="function"/> argument is null.
274 /// <exception cref="System.ArgumentOutOfRangeException">
275 /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
276 /// cref="System.Threading.Tasks.TaskCreationOptions"/>.
278 /// <exception cref="System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
279 /// has already been disposed.
281 public Task(Func
<object?, TResult
> function
, object? state
, CancellationToken cancellationToken
, TaskCreationOptions creationOptions
)
282 : this(function
, state
, Task
.InternalCurrentIfAttached(creationOptions
), cancellationToken
,
283 creationOptions
, InternalTaskOptions
.None
, null)
288 /// Creates a new future object.
290 /// <param name="parent">The parent task for this future.</param>
291 /// <param name="valueSelector">A function that yields the future value.</param>
292 /// <param name="scheduler">The task scheduler which will be used to execute the future.</param>
293 /// <param name="cancellationToken">The CancellationToken for the task.</param>
294 /// <param name="creationOptions">Options to control the future's behavior.</param>
295 /// <param name="internalOptions">Internal options to control the future's behavior.</param>
296 internal Task(Func
<TResult
> valueSelector
, Task
? parent
, CancellationToken cancellationToken
,
297 TaskCreationOptions creationOptions
, InternalTaskOptions internalOptions
, TaskScheduler
? scheduler
) :
298 base(valueSelector
, null, parent
, cancellationToken
, creationOptions
, internalOptions
, scheduler
)
303 /// Creates a new future object.
305 /// <param name="parent">The parent task for this future.</param>
306 /// <param name="state">An object containing data to be used by the action; may be null.</param>
307 /// <param name="valueSelector">A function that yields the future value.</param>
308 /// <param name="cancellationToken">The CancellationToken for the task.</param>
309 /// <param name="scheduler">The task scheduler which will be used to execute the future.</param>
310 /// <param name="creationOptions">Options to control the future's behavior.</param>
311 /// <param name="internalOptions">Internal options to control the future's behavior.</param>
312 internal Task(Delegate valueSelector
, object? state
, Task
? parent
, CancellationToken cancellationToken
,
313 TaskCreationOptions creationOptions
, InternalTaskOptions internalOptions
, TaskScheduler
? scheduler
) :
314 base(valueSelector
, state
, parent
, cancellationToken
, creationOptions
, internalOptions
, scheduler
)
319 // Internal method used by TaskFactory<TResult>.StartNew() methods
320 internal static Task
<TResult
> StartNew(Task
? parent
, Func
<TResult
> function
, CancellationToken cancellationToken
,
321 TaskCreationOptions creationOptions
, InternalTaskOptions internalOptions
, TaskScheduler scheduler
)
323 if (function
== null)
325 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.function
);
327 if (scheduler
== null)
329 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.scheduler
);
332 // Create and schedule the future.
333 Task
<TResult
> f
= new Task
<TResult
>(function
, parent
, cancellationToken
, creationOptions
, internalOptions
| InternalTaskOptions
.QueuedByRuntime
, scheduler
);
335 f
.ScheduleAndStart(false);
339 // Internal method used by TaskFactory<TResult>.StartNew() methods
340 internal static Task
<TResult
> StartNew(Task
? parent
, Func
<object?, TResult
> function
, object? state
, CancellationToken cancellationToken
,
341 TaskCreationOptions creationOptions
, InternalTaskOptions internalOptions
, TaskScheduler scheduler
)
343 if (function
== null)
345 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.function
);
347 if (scheduler
== null)
349 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.scheduler
);
352 // Create and schedule the future.
353 Task
<TResult
> f
= new Task
<TResult
>(function
, state
, parent
, cancellationToken
, creationOptions
, internalOptions
| InternalTaskOptions
.QueuedByRuntime
, scheduler
);
355 f
.ScheduleAndStart(false);
360 private string DebuggerDisplayResultDescription
=>
361 IsCompletedSuccessfully
? "" + m_result
: SR
.TaskT_DebuggerNoResult
;
364 private string DebuggerDisplayMethodDescription
=>
365 m_action
?.Method
.ToString() ?? "{null}";
368 // internal helper function breaks out logic used by TaskCompletionSource
369 internal bool TrySetResult([AllowNull
] TResult result
)
371 Debug
.Assert(m_action
== null, "Task<T>.TrySetResult(): non-null m_action");
373 bool returnValue
= false;
375 // "Reserve" the completion for this task, while making sure that: (1) No prior reservation
376 // has been made, (2) The result has not already been set, (3) An exception has not previously
377 // been recorded, and (4) Cancellation has not been requested.
379 // If the reservation is successful, then set the result and finish completion processing.
380 if (AtomicStateUpdate(TASK_STATE_COMPLETION_RESERVED
,
381 TASK_STATE_COMPLETION_RESERVED
| TASK_STATE_RAN_TO_COMPLETION
| TASK_STATE_FAULTED
| TASK_STATE_CANCELED
))
385 // Signal completion, for waiting tasks
387 // This logic used to be:
389 // However, that goes through a windy code path, involves many non-inlineable functions
390 // and which can be summarized more concisely with the following snippet from
391 // FinishStageTwo, omitting everything that doesn't pertain to TrySetResult.
392 Interlocked
.Exchange(ref m_stateFlags
, m_stateFlags
| TASK_STATE_RAN_TO_COMPLETION
);
393 ContingentProperties
? props
= m_contingentProperties
;
396 NotifyParentIfPotentiallyAttachedTask();
397 props
.SetCompleted();
399 FinishContinuations();
406 // Transitions the promise task into a successfully completed state with the specified result.
407 // This is dangerous, as no synchronization is used, and thus must only be used
408 // before this task is handed out to any consumers, before any continuations are hooked up,
409 // before its wait handle is accessed, etc. It's use is limited to places like in FromAsync
410 // where the operation completes synchronously, and thus we know we can forcefully complete
411 // the task, avoiding expensive completion paths, before the task is actually given to anyone.
412 internal void DangerousSetResult(TResult result
)
414 Debug
.Assert(!IsCompleted
, "The promise must not yet be completed.");
416 // If we have a parent, we need to notify it of the completion. Take the slow path to handle that.
417 if (m_contingentProperties
?.m_parent
!= null)
419 bool success
= TrySetResult(result
);
421 // Nobody else has had a chance to complete this Task yet, so we should succeed.
422 Debug
.Assert(success
);
427 m_stateFlags
|= TASK_STATE_RAN_TO_COMPLETION
;
432 /// Gets the result value of this <see cref="Task{TResult}"/>.
435 /// The get accessor for this property ensures that the asynchronous operation is complete before
436 /// returning. Once the result of the computation is available, it is stored and will be returned
437 /// immediately on later calls to <see cref="Result"/>.
439 [DebuggerBrowsable(DebuggerBrowsableState
.Never
)]
440 public TResult Result
=>
441 IsWaitNotificationEnabledOrNotRanToCompletion
?
442 GetResultCore(waitCompletionNotification
: true) :
446 /// Gets the result value of this <see cref="Task{TResult}"/> once the task has completed successfully.
449 /// This version of Result should only be used if the task completed successfully and if there's
450 /// no debugger wait notification enabled for this task.
452 internal TResult ResultOnSuccess
456 Debug
.Assert(!IsWaitNotificationEnabledOrNotRanToCompletion
,
457 "Should only be used when the task completed successfully and there's no wait notification enabled");
462 // Implements Result. Result delegates to this method if the result isn't already available.
463 internal TResult
GetResultCore(bool waitCompletionNotification
)
465 // If the result has not been calculated yet, wait for it.
466 if (!IsCompleted
) InternalWait(Timeout
.Infinite
, default); // won't throw if task faulted or canceled; that's handled below
468 // Notify the debugger of the wait completion if it's requested such a notification
469 if (waitCompletionNotification
) NotifyDebuggerOfWaitCompletionIfNecessary();
471 // Throw an exception if appropriate.
472 if (!IsCompletedSuccessfully
) ThrowIfExceptional(includeTaskCanceledExceptions
: true);
474 // We shouldn't be here if the result has not been set.
475 Debug
.Assert(IsCompletedSuccessfully
, "Task<T>.Result getter: Expected result to have been set.");
481 /// Provides access to factory methods for creating <see cref="Task{TResult}"/> instances.
484 /// The factory returned from <see cref="Factory"/> is a default instance
485 /// of <see cref="System.Threading.Tasks.TaskFactory{TResult}"/>, as would result from using
486 /// the default constructor on the factory type.
488 public static new TaskFactory
<TResult
> Factory
=> s_Factory
;
491 /// Evaluates the value selector of the Task which is passed in as an object and stores the result.
493 internal override void InnerInvoke()
495 // Invoke the delegate
496 Debug
.Assert(m_action
!= null);
497 if (m_action
is Func
<TResult
> func
)
503 if (m_action
is Func
<object?, TResult
> funcWithState
)
505 m_result
= funcWithState(m_stateObject
);
508 Debug
.Fail("Invalid m_action in Task<TResult>");
511 #region Await Support
513 /// <summary>Gets an awaiter used to await this <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
514 /// <returns>An awaiter instance.</returns>
515 /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
516 public new TaskAwaiter
<TResult
> GetAwaiter()
518 return new TaskAwaiter
<TResult
>(this);
521 /// <summary>Configures an awaiter used to await this <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
522 /// <param name="continueOnCapturedContext">
523 /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
525 /// <returns>An object used to await this task.</returns>
526 public new ConfiguredTaskAwaitable
<TResult
> ConfigureAwait(bool continueOnCapturedContext
)
528 return new ConfiguredTaskAwaitable
<TResult
>(this, continueOnCapturedContext
);
533 #region Continuation methods
535 #region Action<Task<TResult>> continuations
538 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
540 /// <param name="continuationAction">
541 /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
542 /// passed the completed task as an argument.
544 /// <returns>A new continuation <see cref="Task"/>.</returns>
546 /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
547 /// completed, whether it completes due to running to completion successfully, faulting due to an
548 /// unhandled exception, or exiting out early due to being canceled.
550 /// <exception cref="System.ArgumentNullException">
551 /// The <paramref name="continuationAction"/> argument is null.
553 public Task
ContinueWith(Action
<Task
<TResult
>> continuationAction
)
555 return ContinueWith(continuationAction
, TaskScheduler
.Current
, default, TaskContinuationOptions
.None
);
560 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
562 /// <param name="continuationAction">
563 /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
564 /// passed the completed task as an argument.
566 /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
567 /// <returns>A new continuation <see cref="Task"/>.</returns>
569 /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
570 /// completed, whether it completes due to running to completion successfully, faulting due to an
571 /// unhandled exception, or exiting out early due to being canceled.
573 /// <exception cref="System.ArgumentNullException">
574 /// The <paramref name="continuationAction"/> argument is null.
576 /// <exception cref="System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
577 /// has already been disposed.
579 public Task
ContinueWith(Action
<Task
<TResult
>> continuationAction
, CancellationToken cancellationToken
)
581 return ContinueWith(continuationAction
, TaskScheduler
.Current
, cancellationToken
, TaskContinuationOptions
.None
);
586 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
588 /// <param name="continuationAction">
589 /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
590 /// passed the completed task as an argument.
592 /// <param name="scheduler">
593 /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
595 /// <returns>A new continuation <see cref="Task"/>.</returns>
597 /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
598 /// completed, whether it completes due to running to completion successfully, faulting due to an
599 /// unhandled exception, or exiting out early due to being canceled.
601 /// <exception cref="System.ArgumentNullException">
602 /// The <paramref name="continuationAction"/> argument is null.
604 /// <exception cref="System.ArgumentNullException">
605 /// The <paramref name="scheduler"/> argument is null.
607 public Task
ContinueWith(Action
<Task
<TResult
>> continuationAction
, TaskScheduler scheduler
)
609 return ContinueWith(continuationAction
, scheduler
, default, TaskContinuationOptions
.None
);
613 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
615 /// <param name="continuationAction">
616 /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
617 /// passed the completed task as an argument.
619 /// <param name="continuationOptions">
620 /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
622 /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
623 /// well as execution options, such as <see
624 /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
626 /// <returns>A new continuation <see cref="Task"/>.</returns>
628 /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
629 /// completed. If the continuation criteria specified through the <paramref
630 /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled
631 /// instead of scheduled.
633 /// <exception cref="System.ArgumentNullException">
634 /// The <paramref name="continuationAction"/> argument is null.
636 /// <exception cref="System.ArgumentOutOfRangeException">
637 /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
638 /// cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
640 public Task
ContinueWith(Action
<Task
<TResult
>> continuationAction
, TaskContinuationOptions continuationOptions
)
642 return ContinueWith(continuationAction
, TaskScheduler
.Current
, default, continuationOptions
);
646 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
648 /// <param name="continuationAction">
649 /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
650 /// passed the completed task as an argument.
652 /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
653 /// <param name="continuationOptions">
654 /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
656 /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
657 /// well as execution options, such as <see
658 /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
660 /// <param name="scheduler">
661 /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
664 /// <returns>A new continuation <see cref="Task"/>.</returns>
666 /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
667 /// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
668 /// are not met, the continuation task will be canceled instead of scheduled.
670 /// <exception cref="System.ArgumentNullException">
671 /// The <paramref name="continuationAction"/> argument is null.
673 /// <exception cref="System.ArgumentOutOfRangeException">
674 /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
675 /// cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
677 /// <exception cref="System.ArgumentNullException">
678 /// The <paramref name="scheduler"/> argument is null.
680 /// <exception cref="System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
681 /// has already been disposed.
683 public Task
ContinueWith(Action
<Task
<TResult
>> continuationAction
, CancellationToken cancellationToken
,
684 TaskContinuationOptions continuationOptions
, TaskScheduler scheduler
)
686 return ContinueWith(continuationAction
, scheduler
, cancellationToken
, continuationOptions
);
689 // Same as the above overload, only with a stack mark.
690 internal Task
ContinueWith(Action
<Task
<TResult
>> continuationAction
, TaskScheduler scheduler
, CancellationToken cancellationToken
,
691 TaskContinuationOptions continuationOptions
)
693 if (continuationAction
== null)
695 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.continuationAction
);
698 if (scheduler
== null)
700 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.scheduler
);
703 TaskCreationOptions creationOptions
;
704 InternalTaskOptions internalOptions
;
705 CreationOptionsFromContinuationOptions(
708 out internalOptions
);
710 Task continuationTask
= new ContinuationTaskFromResultTask
<TResult
>(
711 this, continuationAction
, null,
712 creationOptions
, internalOptions
715 // Register the continuation. If synchronous execution is requested, this may
716 // actually invoke the continuation before returning.
717 ContinueWithCore(continuationTask
, scheduler
, cancellationToken
, continuationOptions
);
719 return continuationTask
;
723 #region Action<Task<TResult>, Object> continuations
726 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
728 /// <param name="continuationAction">
729 /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
730 /// passed the completed task and the caller-supplied state object as arguments.
732 /// <param name="state">An object representing data to be used by the continuation action.</param>
733 /// <returns>A new continuation <see cref="Task"/>.</returns>
735 /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
736 /// completed, whether it completes due to running to completion successfully, faulting due to an
737 /// unhandled exception, or exiting out early due to being canceled.
739 /// <exception cref="System.ArgumentNullException">
740 /// The <paramref name="continuationAction"/> argument is null.
742 public Task
ContinueWith(Action
<Task
<TResult
>, object?> continuationAction
, object? state
)
744 return ContinueWith(continuationAction
, state
, TaskScheduler
.Current
, default, TaskContinuationOptions
.None
);
749 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
751 /// <param name="continuationAction">
752 /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
753 /// passed the completed task and the caller-supplied state object as arguments.
755 /// <param name="state">An object representing data to be used by the continuation action.</param>
756 /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
757 /// <returns>A new continuation <see cref="Task"/>.</returns>
759 /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
760 /// completed, whether it completes due to running to completion successfully, faulting due to an
761 /// unhandled exception, or exiting out early due to being canceled.
763 /// <exception cref="System.ArgumentNullException">
764 /// The <paramref name="continuationAction"/> argument is null.
766 /// <exception cref="System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
767 /// has already been disposed.
769 public Task
ContinueWith(Action
<Task
<TResult
>, object?> continuationAction
, object? state
, CancellationToken cancellationToken
)
771 return ContinueWith(continuationAction
, state
, TaskScheduler
.Current
, cancellationToken
, TaskContinuationOptions
.None
);
776 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
778 /// <param name="continuationAction">
779 /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
780 /// passed the completed task and the caller-supplied state object as arguments.
782 /// <param name="state">An object representing data to be used by the continuation action.</param>
783 /// <param name="scheduler">
784 /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
786 /// <returns>A new continuation <see cref="Task"/>.</returns>
788 /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
789 /// completed, whether it completes due to running to completion successfully, faulting due to an
790 /// unhandled exception, or exiting out early due to being canceled.
792 /// <exception cref="System.ArgumentNullException">
793 /// The <paramref name="continuationAction"/> argument is null.
795 /// <exception cref="System.ArgumentNullException">
796 /// The <paramref name="scheduler"/> argument is null.
798 public Task
ContinueWith(Action
<Task
<TResult
>, object?> continuationAction
, object? state
, TaskScheduler scheduler
)
800 return ContinueWith(continuationAction
, state
, scheduler
, default, TaskContinuationOptions
.None
);
804 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
806 /// <param name="continuationAction">
807 /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
808 /// passed the completed task and the caller-supplied state object as arguments.
810 /// <param name="state">An object representing data to be used by the continuation action.</param>
811 /// <param name="continuationOptions">
812 /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
814 /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
815 /// well as execution options, such as <see
816 /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
818 /// <returns>A new continuation <see cref="Task"/>.</returns>
820 /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
821 /// completed. If the continuation criteria specified through the <paramref
822 /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled
823 /// instead of scheduled.
825 /// <exception cref="System.ArgumentNullException">
826 /// The <paramref name="continuationAction"/> argument is null.
828 /// <exception cref="System.ArgumentOutOfRangeException">
829 /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
830 /// cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
832 public Task
ContinueWith(Action
<Task
<TResult
>, object?> continuationAction
, object? state
, TaskContinuationOptions continuationOptions
)
834 return ContinueWith(continuationAction
, state
, TaskScheduler
.Current
, default, continuationOptions
);
838 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
840 /// <param name="continuationAction">
841 /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
842 /// passed the completed task and the caller-supplied state object as arguments.
844 /// <param name="state">An object representing data to be used by the continuation action.</param>
845 /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
846 /// <param name="continuationOptions">
847 /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
849 /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
850 /// well as execution options, such as <see
851 /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
853 /// <param name="scheduler">
854 /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
857 /// <returns>A new continuation <see cref="Task"/>.</returns>
859 /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
860 /// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
861 /// are not met, the continuation task will be canceled instead of scheduled.
863 /// <exception cref="System.ArgumentNullException">
864 /// The <paramref name="continuationAction"/> argument is null.
866 /// <exception cref="System.ArgumentOutOfRangeException">
867 /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
868 /// cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
870 /// <exception cref="System.ArgumentNullException">
871 /// The <paramref name="scheduler"/> argument is null.
873 /// <exception cref="System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
874 /// has already been disposed.
876 public Task
ContinueWith(Action
<Task
<TResult
>, object?> continuationAction
, object? state
, CancellationToken cancellationToken
,
877 TaskContinuationOptions continuationOptions
, TaskScheduler scheduler
)
879 return ContinueWith(continuationAction
, state
, scheduler
, cancellationToken
, continuationOptions
);
882 // Same as the above overload, only with a stack mark.
883 internal Task
ContinueWith(Action
<Task
<TResult
>, object?> continuationAction
, object? state
, TaskScheduler scheduler
, CancellationToken cancellationToken
,
884 TaskContinuationOptions continuationOptions
)
886 if (continuationAction
== null)
888 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.continuationAction
);
891 if (scheduler
== null)
893 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.scheduler
);
896 TaskCreationOptions creationOptions
;
897 InternalTaskOptions internalOptions
;
898 CreationOptionsFromContinuationOptions(
901 out internalOptions
);
903 Task continuationTask
= new ContinuationTaskFromResultTask
<TResult
>(
904 this, continuationAction
, state
,
905 creationOptions
, internalOptions
908 // Register the continuation. If synchronous execution is requested, this may
909 // actually invoke the continuation before returning.
910 ContinueWithCore(continuationTask
, scheduler
, cancellationToken
, continuationOptions
);
912 return continuationTask
;
917 #region Func<Task<TResult>,TNewResult> continuations
920 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
922 /// <typeparam name="TNewResult">
923 /// The type of the result produced by the continuation.
925 /// <param name="continuationFunction">
926 /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
927 /// passed the completed task as an argument.
929 /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
931 /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
932 /// task has completed, whether it completes due to running to completion successfully, faulting due
933 /// to an unhandled exception, or exiting out early due to being canceled.
935 /// <exception cref="System.ArgumentNullException">
936 /// The <paramref name="continuationFunction"/> argument is null.
938 public Task
<TNewResult
> ContinueWith
<TNewResult
>(Func
<Task
<TResult
>, TNewResult
> continuationFunction
)
940 return ContinueWith
<TNewResult
>(continuationFunction
, TaskScheduler
.Current
, default, TaskContinuationOptions
.None
);
945 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
947 /// <typeparam name="TNewResult">
948 /// The type of the result produced by the continuation.
950 /// <param name="continuationFunction">
951 /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
952 /// passed the completed task as an argument.
954 /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
955 /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
957 /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
958 /// task has completed, whether it completes due to running to completion successfully, faulting due
959 /// to an unhandled exception, or exiting out early due to being canceled.
961 /// <exception cref="System.ArgumentNullException">
962 /// The <paramref name="continuationFunction"/> argument is null.
964 /// <exception cref="System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
965 /// has already been disposed.
967 public Task
<TNewResult
> ContinueWith
<TNewResult
>(Func
<Task
<TResult
>, TNewResult
> continuationFunction
, CancellationToken cancellationToken
)
969 return ContinueWith
<TNewResult
>(continuationFunction
, TaskScheduler
.Current
, cancellationToken
, TaskContinuationOptions
.None
);
973 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
975 /// <typeparam name="TNewResult">
976 /// The type of the result produced by the continuation.
978 /// <param name="continuationFunction">
979 /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
980 /// passed the completed task as an argument.
982 /// <param name="scheduler">
983 /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
985 /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
987 /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current task has
988 /// completed, whether it completes due to running to completion successfully, faulting due to an
989 /// unhandled exception, or exiting out early due to being canceled.
991 /// <exception cref="System.ArgumentNullException">
992 /// The <paramref name="continuationFunction"/> argument is null.
994 /// <exception cref="System.ArgumentNullException">
995 /// The <paramref name="scheduler"/> argument is null.
997 public Task
<TNewResult
> ContinueWith
<TNewResult
>(Func
<Task
<TResult
>, TNewResult
> continuationFunction
, TaskScheduler scheduler
)
999 return ContinueWith
<TNewResult
>(continuationFunction
, scheduler
, default, TaskContinuationOptions
.None
);
1003 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
1005 /// <typeparam name="TNewResult">
1006 /// The type of the result produced by the continuation.
1008 /// <param name="continuationFunction">
1009 /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
1010 /// passed the completed task as an argument.
1012 /// <param name="continuationOptions">
1013 /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
1015 /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
1016 /// well as execution options, such as <see
1017 /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
1019 /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
1022 /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
1023 /// task has completed, whether it completes due to running to completion successfully, faulting due
1024 /// to an unhandled exception, or exiting out early due to being canceled.
1027 /// The <paramref name="continuationFunction"/>, when executed, should return a <see
1028 /// cref="Task{TNewResult}"/>. This task's completion state will be transferred to the task returned
1029 /// from the ContinueWith call.
1032 /// <exception cref="System.ArgumentNullException">
1033 /// The <paramref name="continuationFunction"/> argument is null.
1035 /// <exception cref="System.ArgumentOutOfRangeException">
1036 /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
1037 /// cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
1039 public Task
<TNewResult
> ContinueWith
<TNewResult
>(Func
<Task
<TResult
>, TNewResult
> continuationFunction
, TaskContinuationOptions continuationOptions
)
1041 return ContinueWith
<TNewResult
>(continuationFunction
, TaskScheduler
.Current
, default, continuationOptions
);
1045 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
1047 /// <typeparam name="TNewResult">
1048 /// The type of the result produced by the continuation.
1050 /// <param name="continuationFunction">
1051 /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be passed as
1052 /// an argument this completed task.
1054 /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
1055 /// <param name="continuationOptions">
1056 /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
1058 /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
1059 /// well as execution options, such as <see
1060 /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
1062 /// <param name="scheduler">
1063 /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
1066 /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
1069 /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current task has
1070 /// completed, whether it completes due to running to completion successfully, faulting due to an
1071 /// unhandled exception, or exiting out early due to being canceled.
1074 /// The <paramref name="continuationFunction"/>, when executed, should return a <see cref="Task{TNewResult}"/>.
1075 /// This task's completion state will be transferred to the task returned from the
1076 /// ContinueWith call.
1079 /// <exception cref="System.ArgumentNullException">
1080 /// The <paramref name="continuationFunction"/> argument is null.
1082 /// <exception cref="System.ArgumentOutOfRangeException">
1083 /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
1084 /// cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
1086 /// <exception cref="System.ArgumentNullException">
1087 /// The <paramref name="scheduler"/> argument is null.
1089 /// <exception cref="System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
1090 /// has already been disposed.
1092 public Task
<TNewResult
> ContinueWith
<TNewResult
>(Func
<Task
<TResult
>, TNewResult
> continuationFunction
, CancellationToken cancellationToken
,
1093 TaskContinuationOptions continuationOptions
, TaskScheduler scheduler
)
1095 return ContinueWith
<TNewResult
>(continuationFunction
, scheduler
, cancellationToken
, continuationOptions
);
1098 // Same as the above overload, just with a stack mark.
1099 internal Task
<TNewResult
> ContinueWith
<TNewResult
>(Func
<Task
<TResult
>, TNewResult
> continuationFunction
, TaskScheduler scheduler
,
1100 CancellationToken cancellationToken
, TaskContinuationOptions continuationOptions
)
1102 if (continuationFunction
== null)
1104 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.continuationFunction
);
1107 if (scheduler
== null)
1109 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.scheduler
);
1112 TaskCreationOptions creationOptions
;
1113 InternalTaskOptions internalOptions
;
1114 CreationOptionsFromContinuationOptions(
1115 continuationOptions
,
1116 out creationOptions
,
1117 out internalOptions
);
1119 Task
<TNewResult
> continuationFuture
= new ContinuationResultTaskFromResultTask
<TResult
, TNewResult
>(
1120 this, continuationFunction
, null,
1121 creationOptions
, internalOptions
1124 // Register the continuation. If synchronous execution is requested, this may
1125 // actually invoke the continuation before returning.
1126 ContinueWithCore(continuationFuture
, scheduler
, cancellationToken
, continuationOptions
);
1128 return continuationFuture
;
1132 #region Func<Task<TResult>, Object,TNewResult> continuations
1135 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
1137 /// <typeparam name="TNewResult">
1138 /// The type of the result produced by the continuation.
1140 /// <param name="continuationFunction">
1141 /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
1142 /// passed the completed task and the caller-supplied state object as arguments.
1144 /// <param name="state">An object representing data to be used by the continuation function.</param>
1145 /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
1147 /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
1148 /// task has completed, whether it completes due to running to completion successfully, faulting due
1149 /// to an unhandled exception, or exiting out early due to being canceled.
1151 /// <exception cref="System.ArgumentNullException">
1152 /// The <paramref name="continuationFunction"/> argument is null.
1154 public Task
<TNewResult
> ContinueWith
<TNewResult
>(Func
<Task
<TResult
>, object?, TNewResult
> continuationFunction
, object? state
)
1156 return ContinueWith
<TNewResult
>(continuationFunction
, state
, TaskScheduler
.Current
, default, TaskContinuationOptions
.None
);
1161 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
1163 /// <typeparam name="TNewResult">
1164 /// The type of the result produced by the continuation.
1166 /// <param name="continuationFunction">
1167 /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
1168 /// passed the completed task and the caller-supplied state object as arguments.
1170 /// <param name="state">An object representing data to be used by the continuation function.</param>
1171 /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
1172 /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
1174 /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
1175 /// task has completed, whether it completes due to running to completion successfully, faulting due
1176 /// to an unhandled exception, or exiting out early due to being canceled.
1178 /// <exception cref="System.ArgumentNullException">
1179 /// The <paramref name="continuationFunction"/> argument is null.
1181 /// <exception cref="System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
1182 /// has already been disposed.
1184 public Task
<TNewResult
> ContinueWith
<TNewResult
>(Func
<Task
<TResult
>, object?, TNewResult
> continuationFunction
, object? state
,
1185 CancellationToken cancellationToken
)
1187 return ContinueWith
<TNewResult
>(continuationFunction
, state
, TaskScheduler
.Current
, cancellationToken
, TaskContinuationOptions
.None
);
1191 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
1193 /// <typeparam name="TNewResult">
1194 /// The type of the result produced by the continuation.
1196 /// <param name="continuationFunction">
1197 /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
1198 /// passed the completed task and the caller-supplied state object as arguments.
1200 /// <param name="state">An object representing data to be used by the continuation function.</param>
1201 /// <param name="scheduler">
1202 /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
1204 /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
1206 /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current task has
1207 /// completed, whether it completes due to running to completion successfully, faulting due to an
1208 /// unhandled exception, or exiting out early due to being canceled.
1210 /// <exception cref="System.ArgumentNullException">
1211 /// The <paramref name="continuationFunction"/> argument is null.
1213 /// <exception cref="System.ArgumentNullException">
1214 /// The <paramref name="scheduler"/> argument is null.
1216 public Task
<TNewResult
> ContinueWith
<TNewResult
>(Func
<Task
<TResult
>, object?, TNewResult
> continuationFunction
, object? state
,
1217 TaskScheduler scheduler
)
1219 return ContinueWith
<TNewResult
>(continuationFunction
, state
, scheduler
, default, TaskContinuationOptions
.None
);
1223 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
1225 /// <typeparam name="TNewResult">
1226 /// The type of the result produced by the continuation.
1228 /// <param name="continuationFunction">
1229 /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
1230 /// passed the completed task and the caller-supplied state object as arguments.
1232 /// <param name="state">An object representing data to be used by the continuation function.</param>
1233 /// <param name="continuationOptions">
1234 /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
1236 /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
1237 /// well as execution options, such as <see
1238 /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
1240 /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
1243 /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
1244 /// task has completed, whether it completes due to running to completion successfully, faulting due
1245 /// to an unhandled exception, or exiting out early due to being canceled.
1248 /// The <paramref name="continuationFunction"/>, when executed, should return a <see
1249 /// cref="Task{TNewResult}"/>. This task's completion state will be transferred to the task returned
1250 /// from the ContinueWith call.
1253 /// <exception cref="System.ArgumentNullException">
1254 /// The <paramref name="continuationFunction"/> argument is null.
1256 /// <exception cref="System.ArgumentOutOfRangeException">
1257 /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
1258 /// cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
1260 public Task
<TNewResult
> ContinueWith
<TNewResult
>(Func
<Task
<TResult
>, object?, TNewResult
> continuationFunction
, object? state
,
1261 TaskContinuationOptions continuationOptions
)
1263 return ContinueWith
<TNewResult
>(continuationFunction
, state
, TaskScheduler
.Current
, default, continuationOptions
);
1267 /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
1269 /// <typeparam name="TNewResult">
1270 /// The type of the result produced by the continuation.
1272 /// <param name="continuationFunction">
1273 /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
1274 /// passed the completed task and the caller-supplied state object as arguments.
1276 /// <param name="state">An object representing data to be used by the continuation function.</param>
1277 /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
1278 /// <param name="continuationOptions">
1279 /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
1281 /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
1282 /// well as execution options, such as <see
1283 /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
1285 /// <param name="scheduler">
1286 /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
1289 /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
1292 /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current task has
1293 /// completed, whether it completes due to running to completion successfully, faulting due to an
1294 /// unhandled exception, or exiting out early due to being canceled.
1297 /// The <paramref name="continuationFunction"/>, when executed, should return a <see cref="Task{TNewResult}"/>.
1298 /// This task's completion state will be transferred to the task returned from the
1299 /// ContinueWith call.
1302 /// <exception cref="System.ArgumentNullException">
1303 /// The <paramref name="continuationFunction"/> argument is null.
1305 /// <exception cref="System.ArgumentOutOfRangeException">
1306 /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
1307 /// cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
1309 /// <exception cref="System.ArgumentNullException">
1310 /// The <paramref name="scheduler"/> argument is null.
1312 /// <exception cref="System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
1313 /// has already been disposed.
1315 public Task
<TNewResult
> ContinueWith
<TNewResult
>(Func
<Task
<TResult
>, object?, TNewResult
> continuationFunction
, object? state
,
1316 CancellationToken cancellationToken
, TaskContinuationOptions continuationOptions
, TaskScheduler scheduler
)
1318 return ContinueWith
<TNewResult
>(continuationFunction
, state
, scheduler
, cancellationToken
, continuationOptions
);
1321 // Same as the above overload, just with a stack mark.
1322 internal Task
<TNewResult
> ContinueWith
<TNewResult
>(Func
<Task
<TResult
>, object?, TNewResult
> continuationFunction
, object? state
,
1323 TaskScheduler scheduler
, CancellationToken cancellationToken
, TaskContinuationOptions continuationOptions
)
1325 if (continuationFunction
== null)
1327 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.continuationFunction
);
1330 if (scheduler
== null)
1332 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.scheduler
);
1335 TaskCreationOptions creationOptions
;
1336 InternalTaskOptions internalOptions
;
1337 CreationOptionsFromContinuationOptions(
1338 continuationOptions
,
1339 out creationOptions
,
1340 out internalOptions
);
1342 Task
<TNewResult
> continuationFuture
= new ContinuationResultTaskFromResultTask
<TResult
, TNewResult
>(
1343 this, continuationFunction
, state
,
1344 creationOptions
, internalOptions
1347 // Register the continuation. If synchronous execution is requested, this may
1348 // actually invoke the continuation before returning.
1349 ContinueWithCore(continuationFuture
, scheduler
, cancellationToken
, continuationOptions
);
1351 return continuationFuture
;
1359 // Proxy class for better debugging experience
1360 internal class SystemThreadingTasks_FutureDebugView
<TResult
>
1362 private readonly Task
<TResult
> m_task
;
1364 public SystemThreadingTasks_FutureDebugView(Task
<TResult
> task
)
1366 Debug
.Assert(task
!= null);
1370 [MaybeNull
] public TResult Result
=> m_task
.Status
== TaskStatus
.RanToCompletion
? m_task
.Result
: default!;
1371 public object? AsyncState
=> m_task
.AsyncState
;
1372 public TaskCreationOptions CreationOptions
=> m_task
.CreationOptions
;
1373 public Exception
? Exception
=> m_task
.Exception
;
1374 public int Id
=> m_task
.Id
;
1375 public bool CancellationPending
=> (m_task
.Status
== TaskStatus
.WaitingToRun
) && m_task
.CancellationToken
.IsCancellationRequested
;
1376 public TaskStatus Status
=> m_task
.Status
;