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