/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }
/// <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)); }