private void Invoke(Task task) { if(m_state == TState.Created) m_state = TState.Running; TState s = TState.Running; AggregateException ex = null; foreach (Task i in m_tasks) { switch (i.m_state) { case TState.Created: case TState.Running: break; case TState.Successful: case TState.Aborted: s= TState.Successful; break; case TState.Faulted: if (ex == null) ex = new AggregateException(); ex.AddException(i.Exception); break; default: throw new InvalidOperationException("Unknown task state: " + i.m_state); } } if(ex!= null && s == TState.Successful) s = TState.Faulted; this.Exception = ex; m_state = s; }
public WhenAnyPromise(Task[] tasks) { this.m_tasks = tasks; foreach (var task in tasks) { if (task.IsCompleted) { this.Invoke(task); // short-circuit the completion action, if possible return; } else task.AddCompletionAction(Invoke); // simple completion action } }
public static Task WhenAny(params Task[] tasks) { // Do some argument checking and make a defensive copy of the tasks array if (tasks == null) throw new ArgumentNullException("Tasks cannot be null"); int taskCount = tasks.Length; if (taskCount == 0) return InternalWhenAny(tasks); // Small optimization in the case of an empty array. Task[] tasksCopy = new Task[taskCount]; for (int i = 0; i < taskCount; i++) { Task task = tasks[i]; if (task == null) throw new ArgumentException("A task cannot be null"); tasksCopy[i] = task; } // The rest can be delegated to InternalWhenAny() return InternalWhenAny(tasksCopy); }
// Some common logic to support WhenAny() methods // tasks should be a defensive copy. private static Task InternalWhenAny(Task[] tasks) { return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait Task.CompletedTask : new WhenAnyPromise(tasks); }
public static Task Run(Action action, ThreadPool tp= null) { Task t = new Task(action); t.RunAsync((tp == null) ? defaultThreadPool : tp); return t; }