/// <summary> /// Creates a task that will complete when any 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 one of the supplied tasks. The return Task's Result is the task that /// completed. /// </returns> /// <remarks> /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in /// the Completed state /// with its Result set to the first task to complete. This is true even if the first task to complete ended in the /// Canceled or Faulted state. /// </remarks> public static CoroutineTask <CoroutineTask> WhenAny(params CoroutineTask[] tasks) { var result = new AsyncResult <CoroutineTask>(true); try { if (tasks == null) { throw new ArgumentNullException("tasks"); } var count = tasks.Length; for (var i = 0; i < count; i++) { CoroutineTask task = tasks[i]; task.asyncResult.Callbackable().OnCallback(ar => { if (!result.IsDone) { result.SetResult(task); } }); } } catch (Exception e) { result.SetException(e); } return(new CoroutineTask <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"); } var count = tasks.Length; var curr = count; var isCancelled = false; var exceptions = new List <Exception>(); for (var i = 0; i < count; i++) { CoroutineTask 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)); }