예제 #1
0
        /// <summary>
        /// Creates a continuation that executes when the target <see cref="CoroutineTask"/> completes.
        /// </summary>
        /// <param name="continuationFunction">
        /// An action to run when the <see cref="CoroutineTask"/> completes. When run, the delegate will be
        /// passed the completed task as an argument.
        /// </param>
        /// <param name="continuationOptions">
        /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
        /// as <see cref="CoroutineTaskContinuationOptions.OnCanceled">OnCanceled</see>
        /// , as well as execution options, such as
        /// <see cref="CoroutineTaskContinuationOptions.OnCompleted">OnCompleted</see>.
        /// </param>
        /// <returns>A new continuation <see cref="CoroutineTask"/>.</returns>
        /// <remarks>
        /// The returned <see cref="CoroutineTask"/> will not be scheduled for execution until the current task has
        /// completed.
        /// </remarks>
        public CoroutineTask <TResult> ContinueWith <TResult>(
            Func <CoroutineTask, IPromise <TResult>, IEnumerator> continuationFunction,
            CoroutineTaskContinuationOptions continuationOptions = CoroutineTaskContinuationOptions.None)
        {
            AsyncResult <TResult> result = new AsyncResult <TResult>(true);

            this._asyncResult.Callbackable().OnCallback(ar =>
            {
                try
                {
                    bool executable = IsExecutable(ar, continuationOptions);
                    if (!executable)
                    {
                        result.SetCancelled();
                        return;
                    }

                    Executors.RunOnCoroutine(continuationFunction(this, result), result);
                }
                catch (Exception e)
                {
                    result.SetException(e);
                }
            });
            return(new CoroutineTask <TResult>(result));
        }
예제 #2
0
        /// <summary>
        /// Creates a continuation that executes when the target <see cref="CoroutineTask"/> completes.
        /// </summary>
        /// <param name="continuationFunction">
        /// An action to run when the <see cref="CoroutineTask"/> completes. When run, the delegate will be
        /// passed the completed task as an argument.
        /// </param>
        /// <param name="continuationOptions">
        /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
        /// as <see cref="CoroutineTaskContinuationOptions.OnCanceled">OnCanceled</see>
        /// , as well as execution options, such as
        /// <see cref="CoroutineTaskContinuationOptions.OnCompleted">OnCompleted</see>.
        /// </param>
        /// <returns>A new continuation <see cref="CoroutineTask"/>.</returns>
        /// <remarks>
        /// The returned <see cref="CoroutineTask"/> will not be scheduled for execution until the current task has
        /// completed.
        /// </remarks>
        public CoroutineTask <TResult> ContinueWith <TResult>(Func <CoroutineTask, TResult> continuationFunction,
                                                              CoroutineTaskContinuationOptions continuationOptions = CoroutineTaskContinuationOptions.None)
        {
            AsyncResult <TResult> result = new AsyncResult <TResult>(true);

            this._asyncResult.Callbackable().OnCallback(ar =>
            {
                try
                {
                    bool executable = IsExecutable(ar, continuationOptions);
                    if (!executable)
                    {
                        result.SetCancelled();
                        return;
                    }

                    TResult value = continuationFunction(this);
                    result.SetResult(value);
                }
                catch (Exception e)
                {
                    result.SetException(e);
                }
            });
            return(new CoroutineTask <TResult>(result));
        }
예제 #3
0
        /// <summary>
        /// Creates a continuation that executes when the target <see cref="CoroutineTask"/> completes.
        /// </summary>
        /// <param name="continuationRoutine">
        /// An action to run when the <see cref="CoroutineTask"/> completes.
        /// </param>
        /// <param name="continuationOptions">
        /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
        /// as <see cref="CoroutineTaskContinuationOptions.OnCanceled">OnCanceled</see>
        /// , as well as execution options, such as
        /// <see cref="CoroutineTaskContinuationOptions.OnCompleted">OnCompleted</see>.
        /// </param>
        /// <returns>A new continuation <see cref="CoroutineTask"/>.</returns>
        /// <remarks>
        /// The returned <see cref="CoroutineTask"/> will not be scheduled for execution until the current task has
        /// completed.
        /// </remarks>
        public CoroutineTask ContinueWith(IEnumerator continuationRoutine,
                                          CoroutineTaskContinuationOptions continuationOptions = CoroutineTaskContinuationOptions.None)
        {
            AsyncResult result = new AsyncResult(true);

            this._asyncResult.Callbackable().OnCallback(ar =>
            {
                try
                {
                    bool executable = IsExecutable(ar, continuationOptions);
                    if (!executable)
                    {
                        result.SetCancelled();
                        return;
                    }

                    Executors.RunOnCoroutine(continuationRoutine, result);
                }
                catch (Exception e)
                {
                    result.SetException(e);
                }
            });
            return(new CoroutineTask(result));
        }
예제 #4
0
        /// <summary>
        /// Creates a continuation that executes when the target <see cref="CoroutineTask"/> completes.
        /// </summary>
        /// <param name="continuationAction">
        /// An action to run when the <see cref="CoroutineTask"/> completes. When run, the delegate will be
        /// passed the completed task as an argument.
        /// </param>
        /// <param name="continuationOptions">
        /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
        /// as <see cref="CoroutineTaskContinuationOptions.OnCanceled">OnCanceled</see>
        /// , as well as execution options, such as
        /// <see cref="CoroutineTaskContinuationOptions.OnCompleted">OnCompleted</see>.
        /// </param>
        /// <returns>A new continuation <see cref="CoroutineTask"/>.</returns>
        /// <remarks>
        /// The returned <see cref="CoroutineTask"/> will not be scheduled for execution until the current task has
        /// completed.
        /// </remarks>
        public CoroutineTask ContinueWith(Action <CoroutineTask> continuationAction,
                                          CoroutineTaskContinuationOptions continuationOptions = CoroutineTaskContinuationOptions.None)
        {
            AsyncResult result = new AsyncResult(true);

            this._asyncResult.Callbackable().OnCallback(ar =>
            {
                try
                {
                    bool executable = IsExecutable(ar, continuationOptions);
                    if (!executable)
                    {
                        result.SetCancelled();
                        return;
                    }

                    continuationAction(this);
                    result.SetResult();
                }
                catch (Exception e)
                {
                    result.SetException(e);
                }
            });
            return(new CoroutineTask(result));
        }
예제 #5
0
        /// <summary>
        ///  Creates a task that will complete when all of the supplied tasks have completed.
        /// </summary>
        /// <param name="tasks">The tasks to wait on for completion.</param>
        /// <returns>A task that represents the completion of all of the supplied tasks.</returns>
        /// <remarks>
        /// <para>
        /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
        /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
        /// </para>
        /// <para>
        /// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
        /// </para>
        /// <para>
        /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the Completed state.
        /// </para>
        /// </remarks>
        public static CoroutineTask WhenAll(params CoroutineTask[] tasks)
        {
            AsyncResult result = new AsyncResult(true);

            try
            {
                if (tasks == null)
                {
                    throw new ArgumentNullException("tasks");
                }

                int              count       = tasks.Length;
                int              curr        = count;
                bool             isCancelled = false;
                List <Exception> exceptions  = new List <Exception>();
                for (int i = 0; i < count; i++)
                {
                    var task = tasks[i];
                    task._asyncResult.Callbackable().OnCallback((ar) =>
                    {
                        isCancelled |= ar.IsCancelled;
                        if (ar.Exception != null)
                        {
                            exceptions.Add(ar.Exception);
                        }

                        if (Interlocked.Decrement(ref curr) <= 0)
                        {
                            if (isCancelled)
                            {
                                result.SetCancelled();
                            }
                            else if (exceptions.Count > 0)
                            {
                                result.SetException(new AggregateException(exceptions));
                            }
                            else
                            {
                                result.SetResult();
                            }
                        }
                    });
                }
            }
            catch (Exception e)
            {
                result.SetException(e);
            }

            return(new CoroutineTask(result));
        }
예제 #6
0
        /// <summary>
        /// Creates a task that will complete when all of the supplied tasks have completed.
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="tasks">The tasks to wait on for completion.</param>
        /// <returns>A task that represents the completion of all of the supplied tasks.</returns>
        /// <remarks>
        /// <para>
        /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
        /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
        /// </para>
        /// <para>
        /// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
        /// </para>
        /// <para>
        /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the Completed state.
        /// The Result of the returned task will be set to an array containing all of the results of the supplied tasks in the
        /// same order as they were provided.
        /// </para>
        /// </remarks>
        public static CoroutineTask <TResult[]> WhenAll <TResult>(params CoroutineTask <TResult>[] tasks)
        {
            AsyncResult <TResult[]> result = new AsyncResult <TResult[]>(true);

            try
            {
                if (tasks == null)
                {
                    throw new ArgumentNullException(nameof(tasks));
                }

                int              count       = tasks.Length;
                int              curr        = count;
                bool             isCancelled = false;
                List <Exception> exceptions  = new List <Exception>();
                TResult[]        array       = new TResult[count];
                for (int i = 0; i < count; i++)
                {
                    int index = i;
                    var t     = tasks[index];
                    t._asyncResult.Callbackable().OnCallback((ar) =>
                    {
                        try
                        {
                            isCancelled |= ar.IsCancelled;
                            if (ar.Exception != null)
                            {
                                exceptions.Add(ar.Exception);
                            }
                            else
                            {
                                array[index] = (TResult)ar.Result;
                            }
                        }
                        finally
                        {
                            if (Interlocked.Decrement(ref curr) <= 0)
                            {
                                if (isCancelled)
                                {
                                    result.SetCancelled();
                                }
                                else if (exceptions.Count > 0)
                                {
                                    result.SetException(new AggregateException(exceptions));
                                }
                                else
                                {
                                    result.SetResult(array);
                                }
                            }
                        }
                    });
                }
            }
            catch (Exception e)
            {
                result.SetException(e);
            }

            return(new CoroutineTask <TResult[]>(result));
        }