网上演练
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1874 lines
107 KiB

#if NET20 || NET30 || NET35 || !NET_4_6
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
namespace System.Threading.Tasks
{
public partial class Task
{
private const int _continuationsInitialization = 1;
private const int _continuationsNotInitialized = 0;
private const int _runningContinuations = 3;
private const int _takingContinuations = 2;
private List<object> _continuations;
private Thread _continuationsOwner;
private int _continuationsStatus;
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
public Task ContinueWith(Action<Task> continuationAction)
{
return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="cancellationToken"> The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
public Task ContinueWith(Action<Task> continuationAction, CancellationToken cancellationToken)
{
return ContinueWith(continuationAction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
public Task ContinueWith(Action<Task> continuationAction, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed. If the continuation criteria specified through the <paramref name="continuationOptions"/> parameter are not met, the continuation task will be canceled
/// instead of scheduled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
public Task ContinueWith(Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
{
return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
/// execution.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
/// are not met, the continuation task will be canceled instead of scheduled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
public Task ContinueWith(Action<Task> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, scheduler, cancellationToken, continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task as and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation action.</param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
public Task ContinueWith(Action<Task, object> continuationAction, object state)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation action.</param>
/// <param name="cancellationToken"> The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
public Task ContinueWith(Action<Task, object> continuationAction, object state, CancellationToken cancellationToken)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation action.</param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
public Task ContinueWith(Action<Task, object> continuationAction, object state, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation action.</param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed. If the continuation criteria specified through the <paramref name="continuationOptions"/> parameter are not met, the continuation task will be canceled
/// instead of scheduled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
public Task ContinueWith(Action<Task, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation action.</param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
/// execution.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
/// are not met, the continuation task will be canceled instead of scheduled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
public Task ContinueWith(Action<Task, object> continuationAction, object state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <typeparam name="TResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction)
{
return ContinueWith(continuationFunction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <typeparam name="TResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
/// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
{
return ContinueWith(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <typeparam name="TResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
/// </param>
/// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskScheduler scheduler)
{
return ContinueWith(continuationFunction, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <typeparam name="TResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
/// completed. If the continuation criteria specified through the <paramref name="continuationOptions"/> parameter are not met, the continuation task will be canceled
/// instead of scheduled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
{
return ContinueWith(continuationFunction, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <typeparam name="TResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
/// execution.
/// </param>
/// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
/// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
/// are not met, the continuation task will be canceled instead of scheduled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith(continuationFunction, scheduler, cancellationToken, continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <typeparam name="TResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation function.</param>
/// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state)
{
return ContinueWith(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <typeparam name="TResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation function.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
/// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken)
{
return ContinueWith(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <typeparam name="TResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation function.</param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
/// </param>
/// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler)
{
return ContinueWith(continuationFunction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <typeparam name="TResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation function.</param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
/// completed. If the continuation criteria specified through the <paramref name="continuationOptions"/> parameter are not met, the continuation task will be canceled
/// instead of scheduled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
{
return ContinueWith(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task"/> completes.
/// </summary>
/// <typeparam name="TResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation function.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
/// execution.
/// </param>
/// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
/// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
/// are not met, the continuation task will be canceled instead of scheduled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith(continuationFunction, state, scheduler, cancellationToken, continuationOptions);
}
/// <summary>
/// Converts TaskContinuationOptions to TaskCreationOptions, and also does
/// some validity checking along the way.
/// </summary>
/// <param name="continuationOptions">Incoming TaskContinuationOptions</param>
/// <param name="creationOptions">Outgoing TaskCreationOptions</param>
/// <param name="internalOptions">Outgoing InternalTaskOptions</param>
internal static void CreationOptionsFromContinuationOptions(TaskContinuationOptions continuationOptions, out TaskCreationOptions creationOptions, out InternalTaskOptions internalOptions)
{
// This is used a couple of times below
const TaskContinuationOptions NotOnAnything = TaskContinuationOptions.NotOnCanceled | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.NotOnRanToCompletion;
const TaskContinuationOptions CreationOptionsMask = TaskContinuationOptions.PreferFairness | TaskContinuationOptions.LongRunning | TaskContinuationOptions.DenyChildAttach | TaskContinuationOptions.HideScheduler | TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.RunContinuationsAsynchronously;
// Check that LongRunning and ExecuteSynchronously are not specified together
const TaskContinuationOptions IllegalMask = TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.LongRunning;
if ((continuationOptions & IllegalMask) == IllegalMask)
{
throw new ArgumentOutOfRangeException("continuationOptions", "The specified TaskContinuationOptions combined LongRunning and ExecuteSynchronously. Synchronous continuations should not be long running.");
}
// Check that no illegal options were specified
if ((continuationOptions & ~(CreationOptionsMask | NotOnAnything | TaskContinuationOptions.LazyCancellation | TaskContinuationOptions.ExecuteSynchronously)) != 0)
{
throw new ArgumentOutOfRangeException("continuationOptions");
}
// Check that we didn't specify "not on anything"
if ((continuationOptions & NotOnAnything) == NotOnAnything)
{
throw new ArgumentOutOfRangeException("continuationOptions", "The specified TaskContinuationOptions excluded all continuation kinds.");
}
// This passes over all but LazyCancellation, which has no representation in TaskCreationOptions
creationOptions = (TaskCreationOptions)(continuationOptions & CreationOptionsMask);
// internalOptions has at least ContinuationTask ...
internalOptions = InternalTaskOptions.ContinuationTask;
// ... and possibly LazyCancellation
if ((continuationOptions & TaskContinuationOptions.LazyCancellation) != 0)
{
internalOptions |= InternalTaskOptions.LazyCancellation;
}
}
internal void ContinueWithCore(Task continuationTask, TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions options)
{
Contract.Requires(continuationTask != null, "Task.ContinueWithCore(): null continuationTask");
Contract.Requires(scheduler != null, "Task.ContinueWithCore(): null scheduler");
Contract.Requires(!continuationTask.IsCompleted, "Did not expect continuationTask to be completed");
// Create a TaskContinuation
TaskContinuation continuation = new StandardTaskContinuation(continuationTask, options, scheduler);
// If cancellationToken is cancellable, then assign it.
if (cancellationToken.CanBeCanceled)
{
if (IsCompleted || cancellationToken.IsCancellationRequested)
{
// If the antecedent has completed, then we will not be queuing up
// the continuation in the antecedent's continuation list. Likewise,
// if the cancellationToken has been canceled, continuationTask will
// be completed in the AssignCancellationToken call below, and there
// is no need to queue the continuation to the antecedent's continuation
// list. In either of these two cases, we will pass "null" for the antecedent,
// meaning "the cancellation callback should not attempt to remove the
// continuation from its antecedent's continuation list".
continuationTask.AssignCancellationToken(cancellationToken, null, null);
}
else
{
// The antecedent is not yet complete, so there is a pretty good chance
// that the continuation will be queued up in the antecedent. Assign the
// cancellation token with information about the antecedent, so that the
// continuation can be dequeued upon the signalling of the token.
//
// It's possible that the antecedent completes before the call to AddTaskContinuation,
// and that is a benign ----. It just means that the cancellation will result in
// a futile search of the antecedent's continuation list.
continuationTask.AssignCancellationToken(cancellationToken, this, continuation);
}
}
// In the case of a pre-canceled token, continuationTask will have been completed
// in a Canceled state by now. If such is the case, there is no need to go through
// the motions of queuing up the continuation for eventual execution.
if (!continuationTask.IsCompleted)
{
// Attempt to enqueue the continuation
var continuationQueued = AddTaskContinuation(continuation, /*addBeforeOthers:*/ false);
// If the continuation was not queued (because the task completed), then run it now.
if (!continuationQueued)
{
continuation.Run(this, true);
}
}
}
/// <summary>
/// Runs all of the continuations, as appropriate.
/// </summary>
internal void FinishContinuations()
{
if (Interlocked.CompareExchange(ref _continuationsStatus, _takingContinuations, _continuationsNotInitialized) == _continuationsNotInitialized)
{
return;
}
if (Interlocked.CompareExchange(ref _continuationsStatus, _takingContinuations, _continuationsInitialization) == _continuationsInitialization)
{
var continuations = Interlocked.CompareExchange(ref _continuations, null, null);
if (continuations == null)
{
return;
}
// Wait for any concurrent adds or removes to be retired
try
{
var spinWait = new SpinWait();
LockEnter(spinWait);
Interlocked.CompareExchange(ref _continuations, null, continuations);
Thread.VolatileWrite(ref _continuationsStatus, _runningContinuations);
}
finally
{
LockExit();
}
// Skip synchronous execution of continuations if this task's thread was aborted
var canInlineContinuations =
Thread.VolatileRead(ref _threadAbortedmanaged) == 0
&& (Thread.CurrentThread.ThreadState != ThreadState.AbortRequested)
&& ((_creationOptions & TaskCreationOptions.RunContinuationsAsynchronously) == 0);
//
// Begin processing of continuation list
//
var continuationCount = continuations.Count;
// Fire the asynchronous continuations first ...
for (var index = 0; index < continuationCount; index++)
{
// Synchronous continuation tasks will have the ExecuteSynchronously option,
// and we're looking for asynchronous tasks...
var tc = continuations[index] as StandardTaskContinuation;
if (tc == null || (tc.Options & TaskContinuationOptions.ExecuteSynchronously) != 0)
{
continue;
}
continuations[index] = null; // so that we can skip this later
tc.Run(this, canInlineContinuations);
}
// ... and then fire the synchronous continuations (if there are any).
// This includes ITaskCompletionAction, AwaitTaskContinuations, and
// Action delegates, which are all by default implicitly synchronous.
for (var index = 0; index < continuationCount; index++)
{
var currentContinuation = continuations[index];
if (currentContinuation == null)
{
continue;
}
continuations[index] = null; // to enable free'ing up memory earlier
// If the continuation is an Action delegate, it came from an await continuation,
// and we should use AwaitTaskContinuation to run it.
var ad = currentContinuation as Action;
if (ad != null)
{
AwaitTaskContinuation.RunOrScheduleAction(ad, canInlineContinuations, ref InternalCurrent);
}
else
{
// If it's a TaskContinuation object of some kind, invoke it.
var tc = currentContinuation as TaskContinuation;
if (tc != null)
{
// We know that this is a synchronous continuation because the
// asynchronous ones have been weeded out
tc.Run(this, canInlineContinuations);
}
// Otherwise, it must be an ITaskCompletionAction, so invoke it.
else
{
Contract.Assert(currentContinuation is ITaskCompletionAction, "Expected continuation element to be Action, TaskContinuation, or ITaskContinuationAction");
var action = (ITaskCompletionAction)currentContinuation;
action.Invoke(this);
}
}
}
}
}
internal void RemoveContinuation(object continuationObject) // could be TaskContinuation or Action<Task>
{
try
{
var continuations = GetContinuations();
if (continuations == null || Status == TaskStatus.RanToCompletion)
{
return;
}
var index = continuations.IndexOf(continuationObject);
if (index != -1)
{
continuations[index] = null;
}
}
finally
{
LockExit();
}
}
// Record a continuation task or action.
// Return true if and only if we successfully queued a continuation.
private bool AddTaskContinuation(object continuationObject, bool addBeforeOthers)
{
Contract.Requires(continuationObject != null);
try
{
var continuations = RetrieveContinuations();
if (continuations == null || Status == TaskStatus.RanToCompletion)
{
return false;
}
if (addBeforeOthers)
{
continuations.Insert(0, continuationObject);
}
else
{
continuations.Add(continuationObject);
}
return true;
}
finally
{
LockExit();
}
}
// Same as the above overload, just with a stack mark parameter.
private Task ContinueWith(Action<Task> continuationAction, TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
// Throw on continuation with null action
if (continuationAction == null)
{
throw new ArgumentNullException("continuationAction");
}
// Throw on continuation with null TaskScheduler
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
Contract.EndContractBlock();
TaskCreationOptions creationOptions;
InternalTaskOptions internalOptions;
CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
Task continuationTask = new ContinuationTaskFromTask
(
this,
continuationAction,
null,
creationOptions,
internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
return continuationTask;
}
// Same as the above overload, just with a stack mark parameter.
private Task ContinueWith(Action<Task, object> continuationAction, object state, TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
// Throw on continuation with null action
if (continuationAction == null)
{
throw new ArgumentNullException("continuationAction");
}
// Throw on continuation with null TaskScheduler
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
Contract.EndContractBlock();
TaskCreationOptions creationOptions;
InternalTaskOptions internalOptions;
CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
Task continuationTask = new ContinuationTaskFromTask
(
this,
continuationAction,
state,
creationOptions,
internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
return continuationTask;
}
// Same as the above overload, just with a stack mark parameter.
private Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
// Throw on continuation with null function
if (continuationFunction == null)
{
throw new ArgumentNullException("continuationFunction");
}
// Throw on continuation with null task scheduler
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
Contract.EndContractBlock();
TaskCreationOptions creationOptions;
InternalTaskOptions internalOptions;
CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>
(
this, continuationFunction, null,
creationOptions,
internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
return continuationTask;
}
// Same as the above overload, just with a stack mark parameter.
private Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
// Throw on continuation with null function
if (continuationFunction == null)
{
throw new ArgumentNullException("continuationFunction");
}
// Throw on continuation with null task scheduler
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
Contract.EndContractBlock();
TaskCreationOptions creationOptions;
InternalTaskOptions internalOptions;
CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>
(
this, continuationFunction, state,
creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
return continuationTask;
}
private List<object> GetContinuations()
{
if (IsCompleted)
{
return null;
}
if (Thread.VolatileRead(ref _continuationsStatus) == _continuationsInitialization)
{
// Initializing or initilized
var spinWait = new SpinWait();
List<object> continuations;
while ((continuations = Interlocked.CompareExchange(ref _continuations, null, null)) == null)
{
spinWait.SpinOnce();
}
LockEnter(spinWait);
if (Thread.VolatileRead(ref _continuationsStatus) == _continuationsInitialization)
{
return continuations;
}
// It is being taken or has already been taken for execution
return null;
}
return null;
}
private void LockEnter(SpinWait spinWait)
{
while (true)
{
if (Interlocked.CompareExchange(ref _continuations, null, null) == null)
{
return;
}
var thread = Interlocked.CompareExchange(ref _continuationsOwner, Thread.CurrentThread, null);
if (thread == null)
{
return;
}
spinWait.SpinOnce();
}
}
private void LockExit()
{
Interlocked.CompareExchange(ref _continuationsOwner, null, Thread.CurrentThread);
}
private List<object> RetrieveContinuations()
{
if (IsCompleted)
{
return null;
}
List<object> continuations = null;
var found = Thread.VolatileRead(ref _continuationsStatus);
var spinWait = new SpinWait();
switch (found)
{
case _continuationsNotInitialized:
// Not initialized
if (Interlocked.CompareExchange(ref _continuationsStatus, _continuationsInitialization, _continuationsNotInitialized) == _continuationsNotInitialized)
{
var created = new List<object>();
continuations = Interlocked.CompareExchange(ref _continuations, created, null);
if (continuations == null)
{
continuations = created;
}
goto default;
}
goto case _continuationsInitialization;
case _continuationsInitialization:
// Initializing or initilized
while (Thread.VolatileRead(ref _continuationsStatus) == _continuationsInitialization && (continuations = Interlocked.CompareExchange(ref _continuations, null, null)) == null)
{
spinWait.SpinOnce();
}
if (Thread.VolatileRead(ref _continuationsStatus) == _takingContinuations)
{
return null;
}
goto default;
case _takingContinuations:
case _runningContinuations:
// Being taken for execution, or
// Already taken for execution
return null;
default:
// The continuations may have already executed at this point
LockEnter(spinWait);
if (Thread.VolatileRead(ref _continuationsStatus) == _continuationsInitialization)
{
return continuations;
}
// It is being taken or has already been taken for execution
return null;
}
}
}
public partial class Task<TResult>
{
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
[MethodImpl(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>> continuationAction)
{
return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>> continuationAction, CancellationToken cancellationToken)
{
return ContinueWith(continuationAction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>> continuationAction, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed. If the continuation criteria specified through the <paramref name="continuationOptions"/> parameter are not met, the continuation task will be canceled
/// instead of scheduled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>> continuationAction, TaskContinuationOptions continuationOptions)
{
return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
/// execution.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
/// are not met, the continuation task will be canceled instead of scheduled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, scheduler, cancellationToken, continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation action.</param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation action.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, CancellationToken cancellationToken)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation action.</param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation action.</param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed. If the continuation criteria specified through the <paramref name="continuationOptions"/> parameter are not met, the continuation task will be canceled
/// instead of scheduled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <param name="continuationAction">
/// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation action.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
/// execution.
/// </param>
/// <returns>A new continuation <see cref="Task"/>.</returns>
/// <remarks>
/// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
/// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
/// are not met, the continuation task will be canceled instead of scheduled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <typeparam name="TNewResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
/// task has completed, whether it completes due to running to completion successfully, faulting due
/// to an unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction)
{
return ContinueWith(continuationFunction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <typeparam name="TNewResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
/// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
/// task has completed, whether it completes due to running to completion successfully, faulting due
/// to an unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, CancellationToken cancellationToken)
{
return ContinueWith(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <typeparam name="TNewResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
/// </param>
/// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, TaskScheduler scheduler)
{
return ContinueWith(continuationFunction, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <typeparam name="TNewResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task as an argument.
/// </param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
/// <remarks>
/// <para>
/// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
/// task has completed, whether it completes due to running to completion successfully, faulting due
/// to an unhandled exception, or exiting out early due to being canceled.
/// </para>
/// <para>
/// The <paramref name="continuationFunction"/>, when executed, should return a <see cref="Task{TNewResult}"/>. This task's completion state will be transferred to the task returned
/// from the ContinueWith call.
/// </para>
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, TaskContinuationOptions continuationOptions)
{
return ContinueWith(continuationFunction, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <typeparam name="TNewResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be passed as
/// an argument this completed task.
/// </param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
/// execution.
/// </param>
/// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
/// <remarks>
/// <para>
/// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </para>
/// <para>
/// The <paramref name="continuationFunction"/>, when executed, should return a <see cref="Task{TNewResult}"/>.
/// This task's completion state will be transferred to the task returned from the
/// ContinueWith call.
/// </para>
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith(continuationFunction, scheduler, cancellationToken, continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <typeparam name="TNewResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation function.</param>
/// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
/// task has completed, whether it completes due to running to completion successfully, faulting due
/// to an unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state)
{
return ContinueWith(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <typeparam name="TNewResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation function.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
/// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
/// task has completed, whether it completes due to running to completion successfully, faulting due
/// to an unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state, CancellationToken cancellationToken)
{
return ContinueWith(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <typeparam name="TNewResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation function.</param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
/// </param>
/// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
/// <remarks>
/// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state, TaskScheduler scheduler)
{
return ContinueWith(continuationFunction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <typeparam name="TNewResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation function.</param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
/// <remarks>
/// <para>
/// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
/// task has completed, whether it completes due to running to completion successfully, faulting due
/// to an unhandled exception, or exiting out early due to being canceled.
/// </para>
/// <para>
/// The <paramref name="continuationFunction"/>, when executed, should return a <see cref="Task{TNewResult}"/>. This task's completion state will be transferred to the task returned
/// from the ContinueWith call.
/// </para>
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
{
return ContinueWith(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
/// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
/// </summary>
/// <typeparam name="TNewResult">
/// The type of the result produced by the continuation.
/// </typeparam>
/// <param name="continuationFunction">
/// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
/// passed the completed task and the caller-supplied state object as arguments.
/// </param>
/// <param name="state">An object representing data to be used by the continuation function.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
/// <param name="continuationOptions">
/// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
/// as <see cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
/// well as execution options, such as <see cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
/// </param>
/// <param name="scheduler">
/// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
/// execution.
/// </param>
/// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
/// <remarks>
/// <para>
/// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current task has
/// completed, whether it completes due to running to completion successfully, faulting due to an
/// unhandled exception, or exiting out early due to being canceled.
/// </para>
/// <para>
/// The <paramref name="continuationFunction"/>, when executed, should return a <see cref="Task{TNewResult}"/>.
/// This task's completion state will be transferred to the task returned from the
/// ContinueWith call.
/// </para>
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
[MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith(continuationFunction, state, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, only with a stack mark.
internal Task ContinueWith(Action<Task<TResult>> continuationAction, TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
if (continuationAction == null)
{
throw new ArgumentNullException("continuationAction");
}
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
TaskCreationOptions creationOptions;
InternalTaskOptions internalOptions;
CreationOptionsFromContinuationOptions
(
continuationOptions,
out creationOptions,
out internalOptions
);
Task continuationTask = new ContinuationTaskFromResultTask<TResult>
(
this,
continuationAction,
null,
creationOptions,
internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
return continuationTask;
}
// Same as the above overload, only with a stack mark.
internal Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
if (continuationAction == null)
{
throw new ArgumentNullException("continuationAction");
}
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
TaskCreationOptions creationOptions;
InternalTaskOptions internalOptions;
CreationOptionsFromContinuationOptions
(
continuationOptions,
out creationOptions,
out internalOptions
);
Task continuationTask = new ContinuationTaskFromResultTask<TResult>
(
this,
continuationAction,
state,
creationOptions,
internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
return continuationTask;
}
// Same as the above overload, just with a stack mark.
internal Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null)
{
throw new ArgumentNullException("continuationFunction");
}
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
TaskCreationOptions creationOptions;
InternalTaskOptions internalOptions;
CreationOptionsFromContinuationOptions(
continuationOptions,
out creationOptions,
out internalOptions);
Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult, TNewResult>(
this, continuationFunction, null,
creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
ContinueWithCore(continuationFuture, scheduler, cancellationToken, continuationOptions);
return continuationFuture;
}
// Same as the above overload, just with a stack mark.
internal Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state, TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null)
{
throw new ArgumentNullException("continuationFunction");
}
if (scheduler == null)
{
throw new ArgumentNullException("scheduler");
}
TaskCreationOptions creationOptions;
InternalTaskOptions internalOptions;
CreationOptionsFromContinuationOptions(
continuationOptions,
out creationOptions,
out internalOptions);
Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult, TNewResult>(
this, continuationFunction, state,
creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
// actually invoke the continuation before returning.
ContinueWithCore(continuationFuture, scheduler, cancellationToken, continuationOptions);
return continuationFuture;
}
}
}
#endif