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
1874 lines
107 KiB
5 years ago
|
#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
|