diff options
Diffstat (limited to 'src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs')
-rw-r--r-- | src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs | 3206 |
1 files changed, 3206 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs b/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs new file mode 100644 index 0000000000..52b471628a --- /dev/null +++ b/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs @@ -0,0 +1,3206 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// +// +// +// There are a plethora of common patterns for which Tasks are created. TaskFactory encodes +// these patterns into helper methods. These helpers also pick up default configuration settings +// applicable to the entire factory and configurable through its constructors. +// +// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +using System; +using System.Collections.Generic; +using System.Security; +using System.Security.Permissions; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Diagnostics.Contracts; + +namespace System.Threading.Tasks +{ + /// <summary> + /// Provides support for creating and scheduling + /// <see cref="T:System.Threading.Tasks.Task">Tasks</see>. + /// </summary> + /// <remarks> + /// <para> + /// There are many common patterns for which tasks are relevant. The <see cref="TaskFactory"/> + /// class encodes some of these patterns into methods that pick up default settings, which are + /// configurable through its constructors. + /// </para> + /// <para> + /// A default instance of <see cref="TaskFactory"/> is available through the + /// <see cref="System.Threading.Tasks.Task.Factory">Task.Factory</see> property. + /// </para> + /// </remarks> + [HostProtection(Synchronization = true, ExternalThreading = true)] + public class TaskFactory + { + // member variables + private CancellationToken m_defaultCancellationToken; + private TaskScheduler m_defaultScheduler; + private TaskCreationOptions m_defaultCreationOptions; + private TaskContinuationOptions m_defaultContinuationOptions; + + + private TaskScheduler DefaultScheduler + { + get + { + if (m_defaultScheduler == null) return TaskScheduler.Current; + else return m_defaultScheduler; + } + } + + // sister method to above property -- avoids a TLS lookup + private TaskScheduler GetDefaultScheduler(Task currTask) + { + if (m_defaultScheduler != null) return m_defaultScheduler; + else if ((currTask != null) + && ((currTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0) + ) + return currTask.ExecutingTaskScheduler; + else return TaskScheduler.Default; + } + + /* Constructors */ + + // ctor parameters provide defaults for the factory, which can be overridden by options provided to + // specific calls on the factory + + + /// <summary> + /// Initializes a <see cref="TaskFactory"/> instance with the default configuration. + /// </summary> + /// <remarks> + /// This constructor creates a <see cref="TaskFactory"/> instance with a default configuration. The + /// <see cref="TaskCreationOptions"/> property is initialized to + /// <see cref="System.Threading.Tasks.TaskCreationOptions.None">TaskCreationOptions.None</see>, the + /// <see cref="TaskContinuationOptions"/> property is initialized to <see + /// cref="System.Threading.Tasks.TaskContinuationOptions.None">TaskContinuationOptions.None</see>, + /// and the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is + /// initialized to the current scheduler (see <see + /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>). + /// </remarks> + public TaskFactory() + : this(default(CancellationToken), TaskCreationOptions.None, TaskContinuationOptions.None, null) + { + } + + /// <summary> + /// Initializes a <see cref="TaskFactory"/> instance with the specified configuration. + /// </summary> + /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned + /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified + /// while calling the factory methods.</param> + /// <remarks> + /// This constructor creates a <see cref="TaskFactory"/> instance with a default configuration. The + /// <see cref="TaskCreationOptions"/> property is initialized to + /// <see cref="System.Threading.Tasks.TaskCreationOptions.None">TaskCreationOptions.None</see>, the + /// <see cref="TaskContinuationOptions"/> property is initialized to <see + /// cref="System.Threading.Tasks.TaskContinuationOptions.None">TaskContinuationOptions.None</see>, + /// and the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is + /// initialized to the current scheduler (see <see + /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>). + /// </remarks> + public TaskFactory(CancellationToken cancellationToken) + : this(cancellationToken, TaskCreationOptions.None, TaskContinuationOptions.None, null) + { + } + + /// <summary> + /// Initializes a <see cref="TaskFactory"/> instance with the specified configuration. + /// </summary> + /// <param name="scheduler"> + /// The <see cref="System.Threading.Tasks.TaskScheduler"> + /// TaskScheduler</see> to use to schedule any tasks created with this TaskFactory. A null value + /// indicates that the current TaskScheduler should be used. + /// </param> + /// <remarks> + /// With this constructor, the + /// <see cref="TaskCreationOptions"/> property is initialized to + /// <see cref="System.Threading.Tasks.TaskCreationOptions.None">TaskCreationOptions.None</see>, the + /// <see cref="TaskContinuationOptions"/> property is initialized to <see + /// cref="System.Threading.Tasks.TaskContinuationOptions.None">TaskContinuationOptions.None</see>, + /// and the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is + /// initialized to <paramref name="scheduler"/>, unless it's null, in which case the property is + /// initialized to the current scheduler (see <see + /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>). + /// </remarks> + public TaskFactory(TaskScheduler scheduler) // null means to use TaskScheduler.Current + : this(default(CancellationToken), TaskCreationOptions.None, TaskContinuationOptions.None, scheduler) + { + } + + /// <summary> + /// Initializes a <see cref="TaskFactory"/> instance with the specified configuration. + /// </summary> + /// <param name="creationOptions"> + /// The default <see cref="System.Threading.Tasks.TaskCreationOptions"> + /// TaskCreationOptions</see> to use when creating tasks with this TaskFactory. + /// </param> + /// <param name="continuationOptions"> + /// The default <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> to use when creating continuation tasks with this TaskFactory. + /// </param> + /// <exception cref="T:System.ArgumentOutOfRangeException"> + /// The exception that is thrown when the + /// <paramref name="creationOptions"/> argument or the <paramref name="continuationOptions"/> + /// argument specifies an invalid value. + /// </exception> + /// <remarks> + /// With this constructor, the + /// <see cref="TaskCreationOptions"/> property is initialized to <paramref name="creationOptions"/>, + /// the + /// <see cref="TaskContinuationOptions"/> property is initialized to <paramref + /// name="continuationOptions"/>, and the <see + /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is initialized to the + /// current scheduler (see <see + /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>). + /// </remarks> + public TaskFactory(TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions) + : this(default(CancellationToken), creationOptions, continuationOptions, null) + { + } + + /// <summary> + /// Initializes a <see cref="TaskFactory"/> instance with the specified configuration. + /// </summary> + /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned + /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified + /// while calling the factory methods.</param> + /// <param name="creationOptions"> + /// The default <see cref="System.Threading.Tasks.TaskCreationOptions"> + /// TaskCreationOptions</see> to use when creating tasks with this TaskFactory. + /// </param> + /// <param name="continuationOptions"> + /// The default <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> to use when creating continuation tasks with this TaskFactory. + /// </param> + /// <param name="scheduler"> + /// The default <see cref="System.Threading.Tasks.TaskScheduler"> + /// TaskScheduler</see> to use to schedule any Tasks created with this TaskFactory. A null value + /// indicates that TaskScheduler.Current should be used. + /// </param> + /// <exception cref="T:System.ArgumentOutOfRangeException"> + /// The exception that is thrown when the + /// <paramref name="creationOptions"/> argument or the <paramref name="continuationOptions"/> + /// argumentspecifies an invalid value. + /// </exception> + /// <remarks> + /// With this constructor, the + /// <see cref="TaskCreationOptions"/> property is initialized to <paramref name="creationOptions"/>, + /// the + /// <see cref="TaskContinuationOptions"/> property is initialized to <paramref + /// name="continuationOptions"/>, and the <see + /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is initialized to + /// <paramref name="scheduler"/>, unless it's null, in which case the property is initialized to the + /// current scheduler (see <see + /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>). + /// </remarks> + public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) + { + CheckMultiTaskContinuationOptions(continuationOptions); + CheckCreationOptions(creationOptions); + + m_defaultCancellationToken = cancellationToken; + m_defaultScheduler = scheduler; + m_defaultCreationOptions = creationOptions; + m_defaultContinuationOptions = continuationOptions; + } + + [ContractArgumentValidatorAttribute] + internal static void CheckCreationOptions(TaskCreationOptions creationOptions) + { + // Check for validity of options + if ((creationOptions & + ~(TaskCreationOptions.AttachedToParent | + TaskCreationOptions.DenyChildAttach | + TaskCreationOptions.HideScheduler | + TaskCreationOptions.LongRunning | + TaskCreationOptions.PreferFairness | + TaskCreationOptions.RunContinuationsAsynchronously)) != 0) + { + throw new ArgumentOutOfRangeException("creationOptions"); + } + Contract.EndContractBlock(); + } + + /* Properties */ + + /// <summary> + /// Gets the default <see cref="System.Threading.CancellationToken">CancellationToken</see> of this + /// TaskFactory. + /// </summary> + /// <remarks> + /// This property returns the default <see cref="CancellationToken"/> that will be assigned to all + /// tasks created by this factory unless another CancellationToken value is explicitly specified + /// during the call to the factory methods. + /// </remarks> + public CancellationToken CancellationToken { get { return m_defaultCancellationToken; } } + + /// <summary> + /// Gets the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> of this + /// TaskFactory. + /// </summary> + /// <remarks> + /// This property returns the default scheduler for this factory. It will be used to schedule all + /// tasks unless another scheduler is explicitly specified during calls to this factory's methods. + /// If null, <see cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see> + /// will be used. + /// </remarks> + public TaskScheduler Scheduler { get { return m_defaultScheduler; } } + + /// <summary> + /// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions + /// </see> value of this TaskFactory. + /// </summary> + /// <remarks> + /// This property returns the default creation options for this factory. They will be used to create all + /// tasks unless other options are explicitly specified during calls to this factory's methods. + /// </remarks> + public TaskCreationOptions CreationOptions { get { return m_defaultCreationOptions; } } + + /// <summary> + /// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskContinuationOptions + /// </see> value of this TaskFactory. + /// </summary> + /// <remarks> + /// This property returns the default continuation options for this factory. They will be used to create + /// all continuation tasks unless other options are explicitly specified during calls to this factory's methods. + /// </remarks> + public TaskContinuationOptions ContinuationOptions { get { return m_defaultContinuationOptions; } } + + // + // StartNew methods + // + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>. + /// </summary> + /// <param name="action">The action delegate to execute asynchronously.</param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="action"/> + /// argument is null.</exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors + /// and then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. However, + /// unless creation and scheduling must be separated, StartNew is the recommended + /// approach for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task StartNew(Action action) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Task currTask = Task.InternalCurrent; + return Task.InternalStartNew(currTask, action, null, m_defaultCancellationToken, GetDefaultScheduler(currTask), + m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark); + } + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>. + /// </summary> + /// <param name="action">The action delegate to execute asynchronously.</param> + /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="action"/> + /// argument is null.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors + /// and then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. However, + /// unless creation and scheduling must be separated, StartNew is the recommended + /// approach for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task StartNew(Action action, CancellationToken cancellationToken) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Task currTask = Task.InternalCurrent; + return Task.InternalStartNew(currTask, action, null, cancellationToken, GetDefaultScheduler(currTask), + m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark); + } + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>. + /// </summary> + /// <param name="action">The action delegate to execute asynchronously.</param> + /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the + /// created + /// <see cref="T:System.Threading.Tasks.Task">Task.</see></param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="action"/> + /// argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and + /// then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task StartNew(Action action, TaskCreationOptions creationOptions) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Task currTask = Task.InternalCurrent; + return Task.InternalStartNew(currTask, action, null, m_defaultCancellationToken, GetDefaultScheduler(currTask), creationOptions, + InternalTaskOptions.None, ref stackMark); + } + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>. + /// </summary> + /// <param name="action">The action delegate to execute asynchronously.</param> + /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new <see cref="Task"/></param> + /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the + /// created + /// <see cref="T:System.Threading.Tasks.Task">Task.</see></param> + /// <param name="scheduler">The <see + /// cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the created <see + /// cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="action"/> + /// argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="scheduler"/> + /// argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and + /// then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task StartNew(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return Task.InternalStartNew( + Task.InternalCurrentIfAttached(creationOptions), action, null, cancellationToken, scheduler, creationOptions, + InternalTaskOptions.None, ref stackMark); + } + + // Internal version includes InternalTaskOptions for Parallel.Invoke() support. + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + internal Task StartNew(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return Task.InternalStartNew( + Task.InternalCurrentIfAttached(creationOptions), action, null, cancellationToken, scheduler, creationOptions, internalOptions, ref stackMark); + } + + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>. + /// </summary> + /// <param name="action">The action delegate to execute asynchronously.</param> + /// <param name="state">An object containing data to be used by the <paramref name="action"/> + /// delegate.</param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="action"/> + /// argument is null.</exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and + /// then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task StartNew(Action<Object> action, Object state) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Task currTask = Task.InternalCurrent; + return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask), + m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark); + } + + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>. + /// </summary> + /// <param name="action">The action delegate to execute asynchronously.</param> + /// <param name="state">An object containing data to be used by the <paramref name="action"/> + /// delegate.</param> + /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new <see cref="Task"/></param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="action"/> + /// argument is null.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and + /// then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task StartNew(Action<Object> action, Object state, CancellationToken cancellationToken) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Task currTask = Task.InternalCurrent; + return Task.InternalStartNew(currTask, action, state, cancellationToken, GetDefaultScheduler(currTask), + m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark); + } + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>. + /// </summary> + /// <param name="action">The action delegate to execute asynchronously.</param> + /// <param name="state">An object containing data to be used by the <paramref name="action"/> + /// delegate.</param> + /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the + /// created + /// <see cref="T:System.Threading.Tasks.Task">Task.</see></param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="action"/> + /// argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and + /// then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task StartNew(Action<Object> action, Object state, TaskCreationOptions creationOptions) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Task currTask = Task.InternalCurrent; + return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask), + creationOptions, InternalTaskOptions.None, ref stackMark); + } + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>. + /// </summary> + /// <param name="action">The action delegate to execute asynchronously.</param> + /// <param name="state">An object containing data to be used by the <paramref name="action"/> + /// delegate.</param> + /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param> + /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the + /// created + /// <see cref="T:System.Threading.Tasks.Task">Task.</see></param> + /// <param name="scheduler">The <see + /// cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the created <see + /// cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="action"/> + /// argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="scheduler"/> + /// argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and + /// then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task StartNew(Action<Object> action, Object state, CancellationToken cancellationToken, + TaskCreationOptions creationOptions, TaskScheduler scheduler) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return Task.InternalStartNew( + Task.InternalCurrentIfAttached(creationOptions), action, state, cancellationToken, scheduler, + creationOptions, InternalTaskOptions.None, ref stackMark); + } + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="function">A function delegate that returns the future result to be available through + /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="function"/> + /// argument is null.</exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one + /// of its constructors and then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> StartNew<TResult>(Func<TResult> function) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Task currTask = Task.InternalCurrent; + return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken, + m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark); + } + + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="function">A function delegate that returns the future result to be available through + /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new <see cref="Task"/></param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="function"/> + /// argument is null.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one + /// of its constructors and then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> StartNew<TResult>(Func<TResult> function, CancellationToken cancellationToken) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Task currTask = Task.InternalCurrent; + return Task<TResult>.StartNew(currTask, function, cancellationToken, + m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark); + } + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="function">A function delegate that returns the future result to be available through + /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the + /// created + /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="function"/> + /// argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one + /// of its constructors and then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> StartNew<TResult>(Func<TResult> function, TaskCreationOptions creationOptions) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Task currTask = Task.InternalCurrent; + return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken, + creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark); + } + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="function">A function delegate that returns the future result to be available through + /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param> + /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the + /// created + /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <param name="scheduler">The <see + /// cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the created <see cref="T:System.Threading.Tasks.Task{TResult}"> + /// Task{TResult}</see>.</param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="function"/> + /// argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="scheduler"/> + /// argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one + /// of its constructors and then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> StartNew<TResult>(Func<TResult> function, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return Task<TResult>.StartNew( + Task.InternalCurrentIfAttached(creationOptions), function, cancellationToken, + creationOptions, InternalTaskOptions.None, scheduler, ref stackMark); + } + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="function">A function delegate that returns the future result to be available through + /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <param name="state">An object containing data to be used by the <paramref name="function"/> + /// delegate.</param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="function"/> + /// argument is null.</exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one + /// of its constructors and then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Task currTask = Task.InternalCurrent; + return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken, + m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark); + } + + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="function">A function delegate that returns the future result to be available through + /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <param name="state">An object containing data to be used by the <paramref name="function"/> + /// delegate.</param> + /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new <see cref="Task"/></param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="function"/> + /// argument is null.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one + /// of its constructors and then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state, CancellationToken cancellationToken) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Task currTask = Task.InternalCurrent; + return Task<TResult>.StartNew(currTask, function, state, cancellationToken, + m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark); + } + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="function">A function delegate that returns the future result to be available through + /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <param name="state">An object containing data to be used by the <paramref name="function"/> + /// delegate.</param> + /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the + /// created + /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="function"/> + /// argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one + /// of its constructors and then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state, TaskCreationOptions creationOptions) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + Task currTask = Task.InternalCurrent; + return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken, + creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark); + } + + /// <summary> + /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="function">A function delegate that returns the future result to be available through + /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <param name="state">An object containing data to be used by the <paramref name="function"/> + /// delegate.</param> + /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param> + /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the + /// created + /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <param name="scheduler">The <see + /// cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the created <see cref="T:System.Threading.Tasks.Task{TResult}"> + /// Task{TResult}</see>.</param> + /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="function"/> + /// argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref + /// name="scheduler"/> + /// argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one + /// of its constructors and then calling + /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. + /// However, unless creation and scheduling must be separated, StartNew is the recommended approach + /// for both simplicity and performance. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state, CancellationToken cancellationToken, + TaskCreationOptions creationOptions, TaskScheduler scheduler) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return Task<TResult>.StartNew( + Task.InternalCurrentIfAttached(creationOptions), function, state, cancellationToken, + creationOptions, InternalTaskOptions.None, scheduler, ref stackMark); + } + + // + // FromAsync methods + // + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that executes an end method action + /// when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes. + /// </summary> + /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the + /// <paramref name="endMethod"/>.</param> + /// <param name="endMethod">The action delegate that processes the completed <paramref + /// name="asyncResult"/>.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="asyncResult"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <returns>A <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the asynchronous + /// operation.</returns> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task FromAsync( + IAsyncResult asyncResult, + Action<IAsyncResult> endMethod) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return FromAsync(asyncResult, endMethod, m_defaultCreationOptions, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that executes an end method action + /// when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes. + /// </summary> + /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the + /// <paramref name="endMethod"/>.</param> + /// <param name="endMethod">The action delegate that processes the completed <paramref + /// name="asyncResult"/>.</param> + /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the + /// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="asyncResult"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <returns>A <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the asynchronous + /// operation.</returns> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task FromAsync( + IAsyncResult asyncResult, + Action<IAsyncResult> endMethod, + TaskCreationOptions creationOptions) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return FromAsync(asyncResult, endMethod, creationOptions, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that executes an end method action + /// when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes. + /// </summary> + /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the + /// <paramref name="endMethod"/>.</param> + /// <param name="endMethod">The action delegate that processes the completed <paramref + /// name="asyncResult"/>.</param> + /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the task that executes the end method.</param> + /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the + /// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="asyncResult"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="scheduler"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <returns>A <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the asynchronous + /// operation.</returns> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task FromAsync( + IAsyncResult asyncResult, + Action<IAsyncResult> endMethod, + TaskCreationOptions creationOptions, + TaskScheduler scheduler) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return FromAsync(asyncResult, endMethod, creationOptions, scheduler, ref stackMark); + } + + // private version that supports StackCrawlMark. + private Task FromAsync( + IAsyncResult asyncResult, + Action<IAsyncResult> endMethod, + TaskCreationOptions creationOptions, + TaskScheduler scheduler, + ref StackCrawlMark stackMark) + { + return TaskFactory<VoidTaskResult>.FromAsyncImpl(asyncResult, null, endMethod, creationOptions, scheduler, ref stackMark); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin + /// and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the + /// asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task FromAsync( + Func<AsyncCallback, object, IAsyncResult> beginMethod, + Action<IAsyncResult> endMethod, + object state) + { + return FromAsync(beginMethod, endMethod, state, m_defaultCreationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin + /// and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the + /// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the + /// asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task FromAsync( + Func<AsyncCallback, object, IAsyncResult> beginMethod, + Action<IAsyncResult> endMethod, object state, TaskCreationOptions creationOptions) + { + return TaskFactory<VoidTaskResult>.FromAsyncImpl(beginMethod, null, endMethod, state, creationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin + /// and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TArg1">The type of the first argument passed to the <paramref + /// name="beginMethod"/> + /// delegate.</typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the + /// asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task FromAsync<TArg1>( + Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod, + Action<IAsyncResult> endMethod, + TArg1 arg1, + object state) + { + return FromAsync(beginMethod, endMethod, arg1, state, m_defaultCreationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin + /// and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TArg1">The type of the first argument passed to the <paramref + /// name="beginMethod"/> + /// delegate.</typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the + /// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the + /// asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task FromAsync<TArg1>( + Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod, + Action<IAsyncResult> endMethod, + TArg1 arg1, object state, TaskCreationOptions creationOptions) + { + return TaskFactory<VoidTaskResult>.FromAsyncImpl(beginMethod, null, endMethod, arg1, state, creationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin + /// and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TArg1">The type of the first argument passed to the <paramref + /// name="beginMethod"/> + /// delegate.</typeparam> + /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/> + /// delegate.</typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the + /// asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task FromAsync<TArg1, TArg2>( + Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod, + Action<IAsyncResult> endMethod, + TArg1 arg1, TArg2 arg2, object state) + { + return FromAsync(beginMethod, endMethod, arg1, arg2, state, m_defaultCreationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin + /// and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TArg1">The type of the first argument passed to the <paramref + /// name="beginMethod"/> + /// delegate.</typeparam> + /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/> + /// delegate.</typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the + /// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the + /// asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task FromAsync<TArg1, TArg2>( + Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod, + Action<IAsyncResult> endMethod, + TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions) + { + return TaskFactory<VoidTaskResult>.FromAsyncImpl(beginMethod, null, endMethod, arg1, arg2, state, creationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin + /// and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TArg1">The type of the first argument passed to the <paramref + /// name="beginMethod"/> + /// delegate.</typeparam> + /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/> + /// delegate.</typeparam> + /// <typeparam name="TArg3">The type of the third argument passed to <paramref name="beginMethod"/> + /// delegate.</typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the + /// asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task FromAsync<TArg1, TArg2, TArg3>( + Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod, + Action<IAsyncResult> endMethod, + TArg1 arg1, TArg2 arg2, TArg3 arg3, object state) + { + return FromAsync(beginMethod, endMethod, arg1, arg2, arg3, state, m_defaultCreationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin + /// and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TArg1">The type of the first argument passed to the <paramref + /// name="beginMethod"/> + /// delegate.</typeparam> + /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/> + /// delegate.</typeparam> + /// <typeparam name="TArg3">The type of the third argument passed to <paramref name="beginMethod"/> + /// delegate.</typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the + /// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the + /// asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task FromAsync<TArg1, TArg2, TArg3>( + Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod, + Action<IAsyncResult> endMethod, + TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions) + { + return TaskFactory<VoidTaskResult>.FromAsyncImpl<TArg1, TArg2, TArg3>(beginMethod, null, endMethod, arg1, arg2, arg3, state, creationOptions); + } + + // + // Additional FromAsync() overloads used for inferencing convenience + // + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that executes an end + /// method function when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the + /// <paramref name="endMethod"/>.</param> + /// <param name="endMethod">The function delegate that processes the completed <paramref + /// name="asyncResult"/>.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="asyncResult"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the + /// asynchronous operation.</returns> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> FromAsync<TResult>( + IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.FromAsyncImpl(asyncResult, endMethod, null, m_defaultCreationOptions, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that executes an end + /// method function when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the + /// <paramref name="endMethod"/>.</param> + /// <param name="endMethod">The function delegate that processes the completed <paramref + /// name="asyncResult"/>.</param> + /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the + /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="asyncResult"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the + /// asynchronous operation.</returns> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> FromAsync<TResult>( + IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod, TaskCreationOptions creationOptions) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.FromAsyncImpl(asyncResult, endMethod, null, creationOptions, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that executes an end + /// method function when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the + /// <paramref name="endMethod"/>.</param> + /// <param name="endMethod">The function delegate that processes the completed <paramref + /// name="asyncResult"/>.</param> + /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the task that executes the end method.</param> + /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the + /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="asyncResult"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="scheduler"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the + /// asynchronous operation.</returns> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> FromAsync<TResult>( + IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod, TaskCreationOptions creationOptions, TaskScheduler scheduler) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.FromAsyncImpl(asyncResult, endMethod, null, creationOptions, scheduler, ref stackMark); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of + /// begin and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that + /// represents the asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task<TResult> FromAsync<TResult>( + Func<AsyncCallback, object, IAsyncResult> beginMethod, + Func<IAsyncResult, TResult> endMethod, object state) + { + return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, state, m_defaultCreationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of + /// begin and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the + /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that + /// represents the asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task<TResult> FromAsync<TResult>( + Func<AsyncCallback, object, IAsyncResult> beginMethod, + Func<IAsyncResult, TResult> endMethod, object state, TaskCreationOptions creationOptions) + { + return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, state, creationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of + /// begin and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TArg1">The type of the first argument passed to the <paramref + /// name="beginMethod"/> delegate.</typeparam> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that + /// represents the asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task<TResult> FromAsync<TArg1, TResult>( + Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod, + Func<IAsyncResult, TResult> endMethod, TArg1 arg1, object state) + { + return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, state, m_defaultCreationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of + /// begin and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TArg1">The type of the first argument passed to the <paramref + /// name="beginMethod"/> delegate.</typeparam> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the + /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that + /// represents the asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task<TResult> FromAsync<TArg1, TResult>(Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod, + Func<IAsyncResult, TResult> endMethod, TArg1 arg1, object state, TaskCreationOptions creationOptions) + { + return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, state, creationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of + /// begin and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TArg1">The type of the first argument passed to the <paramref + /// name="beginMethod"/> delegate.</typeparam> + /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/> + /// delegate.</typeparam> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that + /// represents the asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task<TResult> FromAsync<TArg1, TArg2, TResult>(Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod, + Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object state) + { + return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, m_defaultCreationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of + /// begin and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TArg1">The type of the first argument passed to the <paramref + /// name="beginMethod"/> delegate.</typeparam> + /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/> + /// delegate.</typeparam> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the + /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that + /// represents the asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task<TResult> FromAsync<TArg1, TArg2, TResult>( + Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod, + Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions) + { + return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, creationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of + /// begin and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TArg1">The type of the first argument passed to the <paramref + /// name="beginMethod"/> delegate.</typeparam> + /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/> + /// delegate.</typeparam> + /// <typeparam name="TArg3">The type of the third argument passed to <paramref name="beginMethod"/> + /// delegate.</typeparam> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that + /// represents the asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult>( + Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod, + Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state) + { + return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, m_defaultCreationOptions); + } + + /// <summary> + /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of + /// begin and end methods that conform to the Asynchronous Programming Model pattern. + /// </summary> + /// <typeparam name="TArg1">The type of the first argument passed to the <paramref + /// name="beginMethod"/> delegate.</typeparam> + /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/> + /// delegate.</typeparam> + /// <typeparam name="TArg3">The type of the third argument passed to <paramref name="beginMethod"/> + /// delegate.</typeparam> + /// <typeparam name="TResult">The type of the result available through the + /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>. + /// </typeparam> + /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param> + /// <param name="endMethod">The delegate that ends the asynchronous operation.</param> + /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/> + /// delegate.</param> + /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the + /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/> + /// delegate.</param> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="beginMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="endMethod"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions + /// value.</exception> + /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that + /// represents the asynchronous operation.</returns> + /// <remarks> + /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>. + /// </remarks> + public Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult>( + Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod, + Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions) + { + return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, creationOptions); + } + + /// <summary> + /// Check validity of options passed to FromAsync method + /// </summary> + /// <param name="creationOptions">The options to be validated.</param> + /// <param name="hasBeginMethod">determines type of FromAsync method that called this method</param> + internal static void CheckFromAsyncOptions(TaskCreationOptions creationOptions, bool hasBeginMethod) + { + if (hasBeginMethod) + { + // Options detected here cause exceptions in FromAsync methods that take beginMethod as a parameter + if ((creationOptions & TaskCreationOptions.LongRunning) != 0) + throw new ArgumentOutOfRangeException("creationOptions", Environment.GetResourceString("Task_FromAsync_LongRunning")); + if ((creationOptions & TaskCreationOptions.PreferFairness) != 0) + throw new ArgumentOutOfRangeException("creationOptions", Environment.GetResourceString("Task_FromAsync_PreferFairness")); + } + + // Check for general validity of options + if ((creationOptions & + ~(TaskCreationOptions.AttachedToParent | + TaskCreationOptions.DenyChildAttach | + TaskCreationOptions.HideScheduler | + TaskCreationOptions.PreferFairness | + TaskCreationOptions.LongRunning)) != 0) + { + throw new ArgumentOutOfRangeException("creationOptions"); + } + } + + + // + // ContinueWhenAll methods + // + + // A Task<Task[]> that, given an initial collection of N tasks, will complete when + // it has been invoked N times. This allows us to replace this logic: + // Task<Task[]> promise = new Task<Task[]>(...); + // int _count = tasksCopy.Length; + // Action<Task> completionAction = delegate {if(Interlocked.Decrement(ref _count) == 0) promise.TrySetResult(tasksCopy); + // for(int i=0; i<_count; i++) + // tasksCopy[i].AddCompletionAction(completionAction); + // with this logic: + // CompletionOnCountdownPromise promise = new CompletionOnCountdownPromise(tasksCopy); + // for(int i=0; i<tasksCopy.Length; i++) tasksCopy[i].AddCompletionAction(promise); + // which saves a few allocations. + // + // Used in TaskFactory.CommonCWAllLogic(Task[]), below. + private sealed class CompleteOnCountdownPromise : Task<Task[]>, ITaskCompletionAction + { + private readonly Task[] _tasks; + private int _count; + + internal CompleteOnCountdownPromise(Task[] tasksCopy) : base() + { + Contract.Requires((tasksCopy != null) && (tasksCopy.Length > 0), "Expected non-null task array with at least one element in it"); + _tasks = tasksCopy; + _count = tasksCopy.Length; + + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "TaskFactory.ContinueWhenAll", 0); + + if (Task.s_asyncDebuggingEnabled) + { + AddToActiveTasks(this); + } + } + + public void Invoke(Task completingTask) + { + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Join); + + if (completingTask.IsWaitNotificationEnabled) this.SetNotificationForWaitCompletion(enabled: true); + if (Interlocked.Decrement(ref _count) == 0) + { + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed); + + if (Task.s_asyncDebuggingEnabled) + { + RemoveFromActiveTasks(this.Id); + } + + TrySetResult(_tasks); + } + Contract.Assert(_count >= 0, "Count should never go below 0"); + } + + public bool InvokeMayRunArbitraryCode { get { return true; } } + + /// <summary> + /// Returns whether we should notify the debugger of a wait completion. This returns + /// true iff at least one constituent task has its bit set. + /// </summary> + internal override bool ShouldNotifyDebuggerOfWaitCompletion + { + get + { + return + base.ShouldNotifyDebuggerOfWaitCompletion && + Task.AnyTaskRequiresNotifyDebuggerOfWaitCompletion(_tasks); + } + } + } + + // Performs some logic common to all ContinueWhenAll() overloads + internal static Task<Task[]> CommonCWAllLogic(Task[] tasksCopy) + { + Contract.Requires(tasksCopy != null); + + // Create a promise task to be returned to the user + CompleteOnCountdownPromise promise = new CompleteOnCountdownPromise(tasksCopy); + + for (int i = 0; i < tasksCopy.Length; i++) + { + if (tasksCopy[i].IsCompleted) promise.Invoke(tasksCopy[i]); // Short-circuit the completion action, if possible + else tasksCopy[i].AddCompletionAction(promise); // simple completion action + } + + return promise; + } + + + // A Task<Task<T>[]> that, given an initial collection of N tasks, will complete when + // it has been invoked N times. See comments for non-generic CompleteOnCountdownPromise class. + // + // Used in TaskFactory.CommonCWAllLogic<TResult>(Task<TResult>[]), below. + private sealed class CompleteOnCountdownPromise<T> : Task<Task<T>[]>, ITaskCompletionAction + { + private readonly Task<T>[] _tasks; + private int _count; + + internal CompleteOnCountdownPromise(Task<T>[] tasksCopy) : base() + { + Contract.Requires((tasksCopy != null) && (tasksCopy.Length > 0), "Expected non-null task array with at least one element in it"); + _tasks = tasksCopy; + _count = tasksCopy.Length; + + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "TaskFactory.ContinueWhenAll<>", 0); + + if (Task.s_asyncDebuggingEnabled) + { + AddToActiveTasks(this); + } + } + + public void Invoke(Task completingTask) + { + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Join); + + if (completingTask.IsWaitNotificationEnabled) this.SetNotificationForWaitCompletion(enabled: true); + if (Interlocked.Decrement(ref _count) == 0) + { + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed); + + if (Task.s_asyncDebuggingEnabled) + { + RemoveFromActiveTasks(this.Id); + } + + TrySetResult(_tasks); + } + Contract.Assert(_count >= 0, "Count should never go below 0"); + } + + public bool InvokeMayRunArbitraryCode { get { return true; } } + + /// <summary> + /// Returns whether we should notify the debugger of a wait completion. This returns + /// true iff at least one constituent task has its bit set. + /// </summary> + internal override bool ShouldNotifyDebuggerOfWaitCompletion + { + get + { + return + base.ShouldNotifyDebuggerOfWaitCompletion && + Task.AnyTaskRequiresNotifyDebuggerOfWaitCompletion(_tasks); + } + } + } + + + internal static Task<Task<T>[]> CommonCWAllLogic<T>(Task<T>[] tasksCopy) + { + Contract.Requires(tasksCopy != null); + + // Create a promise task to be returned to the user + CompleteOnCountdownPromise<T> promise = new CompleteOnCountdownPromise<T>(tasksCopy); + + for (int i = 0; i < tasksCopy.Length; i++) + { + if (tasksCopy[i].IsCompleted) promise.Invoke(tasksCopy[i]); // Short-circuit the completion action, if possible + else tasksCopy[i].AddCompletionAction(promise); // simple completion action + } + + return promise; + } + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationAction">The action delegate to execute when all tasks in + /// the <paramref name="tasks"/> array have completed.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationAction">The action delegate to execute when all tasks in + /// the <paramref name="tasks"/> array have completed.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</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 ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction, CancellationToken cancellationToken) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationAction">The action delegate to execute when all tasks in the <paramref + /// name="tasks"/> array have completed.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAll. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction, TaskContinuationOptions continuationOptions) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationAction">The action delegate to execute when all tasks in the <paramref + /// name="tasks"/> array have completed.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the created continuation <see + /// cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="scheduler"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAll. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction, CancellationToken cancellationToken, + TaskContinuationOptions continuationOptions, TaskScheduler scheduler) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationAction">The action delegate to execute when all tasks in + /// the <paramref name="tasks"/> array have completed.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationAction">The action delegate to execute when all tasks in + /// the <paramref name="tasks"/> array have completed.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</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 ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction, + CancellationToken cancellationToken) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationAction">The action delegate to execute when all tasks in the <paramref + /// name="tasks"/> array have completed.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAll. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction, + TaskContinuationOptions continuationOptions) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationAction">The action delegate to execute when all tasks in the <paramref + /// name="tasks"/> array have completed.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the created continuation <see + /// cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="scheduler"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAll. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction, + CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationFunction">The function delegate to execute when all tasks in the + /// <paramref name="tasks"/> array have completed.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationFunction">The function delegate to execute when all tasks in the + /// <paramref name="tasks"/> array have completed.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</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<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction, CancellationToken cancellationToken) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationFunction">The function delegate to execute when all tasks in the + /// <paramref name="tasks"/> array have completed.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAll. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction, TaskContinuationOptions continuationOptions) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationFunction">The function delegate to execute when all tasks in the + /// <paramref name="tasks"/> array have completed.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the created continuation <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="scheduler"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAll. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction, CancellationToken cancellationToken, + TaskContinuationOptions continuationOptions, TaskScheduler scheduler) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark); + } + + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationFunction">The function delegate to execute when all tasks in the + /// <paramref name="tasks"/> array have completed.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationFunction">The function delegate to execute when all tasks in the + /// <paramref name="tasks"/> array have completed.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</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<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction, + CancellationToken cancellationToken) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationFunction">The function delegate to execute when all tasks in the + /// <paramref name="tasks"/> array have completed.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAll. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction, + TaskContinuationOptions continuationOptions) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of a set of provided Tasks. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue.</param> + /// <param name="continuationFunction">The function delegate to execute when all tasks in the + /// <paramref name="tasks"/> array have completed.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the created continuation <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="scheduler"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAll. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction, + CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark); + } + + // + // ContinueWhenAny methods + // + + // A Task<Task> that will be completed the first time that Invoke is called. + // It allows us to replace this logic: + // Task<Task> promise = new Task<Task>(...); + // Action<Task> completionAction = delegate(Task completingTask) { promise.TrySetResult(completingTask); } + // for(int i=0; i<tasksCopy.Length; i++) tasksCopy[i].AddCompletionAction(completionAction); + // with this logic: + // CompletionOnInvokePromise promise = new CompletionOnInvokePromise(tasksCopy); + // for(int i=0; i<tasksCopy.Length; i++) tasksCopy[i].AddCompletionAction(promise); + // which saves a couple of allocations. + // + // Used in TaskFactory.CommonCWAnyLogic(), below. + internal sealed class CompleteOnInvokePromise : Task<Task>, ITaskCompletionAction + { + private IList<Task> _tasks; // must track this for cleanup + private int m_firstTaskAlreadyCompleted; + + public CompleteOnInvokePromise(IList<Task> tasks) : base() + { + Contract.Requires(tasks != null, "Expected non-null collection of tasks"); + _tasks = tasks; + + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "TaskFactory.ContinueWhenAny", 0); + + if (Task.s_asyncDebuggingEnabled) + { + AddToActiveTasks(this); + } + } + + public void Invoke(Task completingTask) + { + if (Interlocked.CompareExchange(ref m_firstTaskAlreadyCompleted, 1, 0) == 0) + { + if (AsyncCausalityTracer.LoggingOn) + { + AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Choice); + AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed); + } + + if (Task.s_asyncDebuggingEnabled) + { + RemoveFromActiveTasks(this.Id); + } + + bool success = TrySetResult(completingTask); + Contract.Assert(success, "Only one task should have gotten to this point, and thus this must be successful."); + + // We need to remove continuations that may be left straggling on other tasks. + // Otherwise, repeated calls to WhenAny using the same task could leak actions. + // This may also help to avoided unnecessary invocations of this whenComplete delegate. + // Note that we may be attempting to remove a continuation from a task that hasn't had it + // added yet; while there's overhead there, the operation won't hurt anything. + var tasks = _tasks; + int numTasks = tasks.Count; + for (int i = 0; i < numTasks; i++) + { + var task = tasks[i]; + if (task != null && // if an element was erroneously nulled out concurrently, just skip it; worst case is we don't remove a continuation + !task.IsCompleted) task.RemoveContinuation(this); + } + _tasks = null; + + } + } + + public bool InvokeMayRunArbitraryCode { get { return true; } } + } + // Common ContinueWhenAny logic + // If the tasks list is not an array, it must be an internal defensive copy so that + // we don't need to be concerned about concurrent modifications to the list. If the task list + // is an array, it should be a defensive copy if this functionality is being used + // asynchronously (e.g. WhenAny) rather than synchronously (e.g. WaitAny). + internal static Task<Task> CommonCWAnyLogic(IList<Task> tasks) + { + Contract.Requires(tasks != null); + + // Create a promise task to be returned to the user + var promise = new CompleteOnInvokePromise(tasks); + + // At the completion of any of the tasks, complete the promise. + + bool checkArgsOnly = false; + int numTasks = tasks.Count; + for(int i=0; i<numTasks; i++) + { + var task = tasks[i]; + if (task == null) throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks"); + + if (checkArgsOnly) continue; + + // If the promise has already completed, don't bother with checking any more tasks. + if (promise.IsCompleted) + { + checkArgsOnly = true; + } + // If a task has already completed, complete the promise. + else if (task.IsCompleted) + { + promise.Invoke(task); + checkArgsOnly = true; + } + // Otherwise, add the completion action and keep going. + else task.AddCompletionAction(promise); + } + + return promise; + } + + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationAction">The action delegate to execute when one task in the <paramref + /// name="tasks"/> array completes.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationAction">The action delegate to execute when one task in the <paramref + /// name="tasks"/> array completes.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</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 ContinueWhenAny(Task[] tasks, Action<Task> continuationAction, CancellationToken cancellationToken) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationAction">The action delegate to execute when one task in the <paramref + /// name="tasks"/> array completes.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAny. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction, TaskContinuationOptions continuationOptions) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationAction">The action delegate to execute when one task in the <paramref + /// name="tasks"/> array completes.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the created continuation <see + /// cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="scheduler"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAny. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction, CancellationToken cancellationToken, + TaskContinuationOptions continuationOptions, TaskScheduler scheduler) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler, ref stackMark); + } + + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationFunction">The function delegate to execute when one task in the + /// <paramref name="tasks"/> array completes.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationFunction">The function delegate to execute when one task in the + /// <paramref name="tasks"/> array completes.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</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<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction, CancellationToken cancellationToken) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationFunction">The function delegate to execute when one task in the + /// <paramref name="tasks"/> array completes.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAny. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null,continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationFunction">The function delegate to execute when one task in the + /// <paramref name="tasks"/> array completes.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the created continuation <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="scheduler"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAny. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction, CancellationToken cancellationToken, + TaskContinuationOptions continuationOptions, TaskScheduler scheduler) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationFunction">The function delegate to execute when one task in the + /// <paramref name="tasks"/> array completes.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction) + { + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationFunction">The function delegate to execute when one task in the + /// <paramref name="tasks"/> array completes.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</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<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction, + CancellationToken cancellationToken) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationFunction">The function delegate to execute when one task in the + /// <paramref name="tasks"/> array completes.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAny. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction, + TaskContinuationOptions continuationOptions) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <typeparam name="TResult">The type of the result that is returned by the <paramref + /// name="continuationFunction"/> + /// delegate and associated with the created <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationFunction">The function delegate to execute when one task in the + /// <paramref name="tasks"/> array completes.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param> + /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the created continuation <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationFunction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="scheduler"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAny. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction, + CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) + { + if (continuationFunction == null) throw new ArgumentNullException("continuationFunction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark); + } + + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationAction">The action delegate to execute when one task in the + /// <paramref name="tasks"/> array completes.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationAction">The action delegate to execute when one task in the + /// <paramref name="tasks"/> array completes.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</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 ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction, + CancellationToken cancellationToken) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationAction">The action delegate to execute when one task in the + /// <paramref name="tasks"/> array completes.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAny. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction, + TaskContinuationOptions continuationOptions) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark); + } + + /// <summary> + /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see> + /// that will be started upon the completion of any Task in the provided set. + /// </summary> + /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam> + /// <param name="tasks">The array of tasks from which to continue when one task completes.</param> + /// <param name="continuationAction">The action delegate to execute when one task in the + /// <paramref name="tasks"/> array completes.</param> + /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// that will be assigned to the new continuation task.</param> + /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions"> + /// TaskContinuationOptions</see> value that controls the behavior of + /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param> + /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> + /// that is used to schedule the created continuation <see + /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param> + /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task"/>.</returns> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="tasks"/> array is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="continuationAction"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the + /// <paramref name="scheduler"/> argument is null.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array contains a null value.</exception> + /// <exception cref="T:System.ArgumentException">The exception that is thrown when the + /// <paramref name="tasks"/> array is empty.</exception> + /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the + /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions + /// value.</exception> + /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see> + /// has already been disposed. + /// </exception> + /// <remarks> + /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>, + /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation + /// will be executed, are illegal with ContinueWhenAny. + /// </remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction, + CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) + { + if (continuationAction == null) throw new ArgumentNullException("continuationAction"); + Contract.EndContractBlock(); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler, ref stackMark); + } + + // Check task array and return a defensive copy. + // Used with ContinueWhenAll()/ContinueWhenAny(). + internal static Task[] CheckMultiContinuationTasksAndCopy(Task[] tasks) + { + if (tasks == null) + throw new ArgumentNullException("tasks"); + if (tasks.Length == 0) + throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), "tasks"); + Contract.EndContractBlock(); + + Task[] tasksCopy = new Task[tasks.Length]; + for (int i = 0; i < tasks.Length; i++) + { + tasksCopy[i] = tasks[i]; + + if (tasksCopy[i] == null) + throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks"); + } + + return tasksCopy; + } + + internal static Task<TResult>[] CheckMultiContinuationTasksAndCopy<TResult>(Task<TResult>[] tasks) + { + if (tasks == null) + throw new ArgumentNullException("tasks"); + if (tasks.Length == 0) + throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), "tasks"); + Contract.EndContractBlock(); + + Task<TResult>[] tasksCopy = new Task<TResult>[tasks.Length]; + for (int i = 0; i < tasks.Length; i++) + { + tasksCopy[i] = tasks[i]; + + if (tasksCopy[i] == null) + throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks"); + } + + return tasksCopy; + } + + // Throw an exception if "options" argument specifies illegal options + [ContractArgumentValidatorAttribute] + internal static void CheckMultiTaskContinuationOptions(TaskContinuationOptions continuationOptions) + { + // Construct a mask to check for illegal options + const TaskContinuationOptions NotOnAny = TaskContinuationOptions.NotOnCanceled | + TaskContinuationOptions.NotOnFaulted | + TaskContinuationOptions.NotOnRanToCompletion; + + // Check that LongRunning and ExecuteSynchronously are not specified together + const TaskContinuationOptions illegalMask = TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.LongRunning; + if ((continuationOptions & illegalMask) == illegalMask) + { + throw new ArgumentOutOfRangeException("continuationOptions", Environment.GetResourceString("Task_ContinueWith_ESandLR")); + } + + // Check that no nonsensical options are specified. + if ((continuationOptions & ~( + TaskContinuationOptions.LongRunning | + TaskContinuationOptions.PreferFairness | + TaskContinuationOptions.AttachedToParent | + TaskContinuationOptions.DenyChildAttach | + TaskContinuationOptions.HideScheduler | + TaskContinuationOptions.LazyCancellation | + NotOnAny | + TaskContinuationOptions.ExecuteSynchronously)) != 0) + { + throw new ArgumentOutOfRangeException("continuationOptions"); + } + + // Check that no "fire" options are specified. + if ((continuationOptions & NotOnAny) != 0) + throw new ArgumentOutOfRangeException("continuationOptions", Environment.GetResourceString("Task_MultiTaskContinuation_FireOptions")); + Contract.EndContractBlock(); + } + } + +} |