5 // Marek Safar <marek.safar@gmail.com>
6 // Jérémie Laval <jeremie dot laval at xamarin dot com>
8 // Copyright (c) 2008 Jérémie "Garuma" Laval
9 // Copyright 2011 Xamarin Inc (http://www.xamarin.com).
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
34 using System.Threading;
35 using System.Collections.Concurrent;
36 using System.Collections.Generic;
37 using System.Runtime.CompilerServices;
39 namespace System.Threading.Tasks
41 [System.Diagnostics.DebuggerDisplay ("Id = {Id}, Status = {Status}")]
42 [System.Diagnostics.DebuggerTypeProxy (typeof (TaskDebuggerView))]
43 public class Task : IDisposable, IAsyncResult
45 const TaskCreationOptions TaskCreationOptionsContinuation = (TaskCreationOptions) (1 << 10);
47 // With this attribute each thread has its own value so that it's correct for our Schedule code
48 // and for Parent property.
52 static Action<Task> childWorkAdder;
57 static readonly TaskFactory defaultFactory = new TaskFactory ();
59 CountdownEvent childTasks;
62 TaskCreationOptions taskCreationOptions;
64 internal TaskScheduler scheduler;
66 volatile AggregateException exception;
67 volatile bool exceptionObserved;
68 ConcurrentQueue<AggregateException> childExceptions;
72 TaskActionInvoker invoker;
74 AtomicBooleanValue executing;
76 TaskCompletionQueue<IContinuation> continuations;
77 TaskCompletionQueue<IEventSlot> registeredEvts;
79 CancellationToken token;
80 CancellationTokenRegistration? cancellationRegistration;
82 internal const TaskCreationOptions WorkerTaskNotSupportedOptions = TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness;
84 const TaskCreationOptions MaxTaskCreationOptions =
86 TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler |
88 TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent;
90 public Task (Action action)
91 : this (action, TaskCreationOptions.None)
96 public Task (Action action, TaskCreationOptions creationOptions)
97 : this (action, CancellationToken.None, creationOptions)
102 public Task (Action action, CancellationToken cancellationToken)
103 : this (action, cancellationToken, TaskCreationOptions.None)
108 public Task (Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
109 : this (TaskActionInvoker.Create (action), null, cancellationToken, creationOptions, current)
112 throw new ArgumentNullException ("action");
113 if (creationOptions > MaxTaskCreationOptions || creationOptions < TaskCreationOptions.None)
114 throw new ArgumentOutOfRangeException ("creationOptions");
117 public Task (Action<object> action, object state)
118 : this (action, state, TaskCreationOptions.None)
122 public Task (Action<object> action, object state, TaskCreationOptions creationOptions)
123 : this (action, state, CancellationToken.None, creationOptions)
127 public Task (Action<object> action, object state, CancellationToken cancellationToken)
128 : this (action, state, cancellationToken, TaskCreationOptions.None)
132 public Task (Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
133 : this (TaskActionInvoker.Create (action), state, cancellationToken, creationOptions, current)
136 throw new ArgumentNullException ("action");
137 if (creationOptions > MaxTaskCreationOptions || creationOptions < TaskCreationOptions.None)
138 throw new ArgumentOutOfRangeException ("creationOptions");
141 internal Task (TaskActionInvoker invoker, object state, CancellationToken cancellationToken,
142 TaskCreationOptions creationOptions, Task parent)
144 this.invoker = invoker;
145 this.taskCreationOptions = creationOptions;
147 this.taskId = Interlocked.Increment (ref id);
148 this.status = cancellationToken.IsCancellationRequested ? TaskStatus.Canceled : TaskStatus.Created;
149 this.token = cancellationToken;
150 this.parent = parent;
152 // Process taskCreationOptions
153 if (CheckTaskOptions (taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null)
156 if (token.CanBeCanceled)
157 cancellationRegistration = token.Register (l => ((Task) l).CancelReal (), this);
162 if (exception != null && !exceptionObserved)
166 bool CheckTaskOptions (TaskCreationOptions opt, TaskCreationOptions member)
168 return (opt & member) == member;
174 Start (TaskScheduler.Current);
177 public void Start (TaskScheduler scheduler)
179 if (scheduler == null)
180 throw new ArgumentNullException ("scheduler");
182 if (status >= TaskStatus.WaitingToRun)
183 throw new InvalidOperationException ("The Task is not in a valid state to be started.");
186 throw new InvalidOperationException ("Start may not be called on a continuation task");
188 SetupScheduler (scheduler);
192 internal void SetupScheduler (TaskScheduler scheduler)
194 this.scheduler = scheduler;
195 Status = TaskStatus.WaitingForActivation;
198 public void RunSynchronously ()
200 RunSynchronously (TaskScheduler.Current);
203 public void RunSynchronously (TaskScheduler scheduler)
205 if (scheduler == null)
206 throw new ArgumentNullException ("scheduler");
208 if (Status > TaskStatus.WaitingForActivation)
209 throw new InvalidOperationException ("The task is not in a valid state to be started");
211 SetupScheduler (scheduler);
212 var saveStatus = status;
213 Status = TaskStatus.WaitingToRun;
216 if (scheduler.RunInline (this))
218 } catch (Exception inner) {
219 throw new TaskSchedulerException (inner);
229 public Task ContinueWith (Action<Task> continuationAction)
231 return ContinueWith (continuationAction, TaskContinuationOptions.None);
234 public Task ContinueWith (Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
236 return ContinueWith (continuationAction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
239 public Task ContinueWith (Action<Task> continuationAction, CancellationToken cancellationToken)
241 return ContinueWith (continuationAction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
244 public Task ContinueWith (Action<Task> continuationAction, TaskScheduler scheduler)
246 return ContinueWith (continuationAction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
249 public Task ContinueWith (Action<Task> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
251 if (continuationAction == null)
252 throw new ArgumentNullException ("continuationAction");
253 if (scheduler == null)
254 throw new ArgumentNullException ("scheduler");
256 return ContinueWith (TaskActionInvoker.Create (continuationAction), cancellationToken, continuationOptions, scheduler);
259 internal Task ContinueWith (TaskActionInvoker invoker, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
261 var continuation = new Task (invoker, null, cancellationToken, GetCreationOptions (continuationOptions), this);
262 ContinueWithCore (continuation, continuationOptions, scheduler);
267 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction)
269 return ContinueWith<TResult> (continuationFunction, TaskContinuationOptions.None);
272 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
274 return ContinueWith<TResult> (continuationFunction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
277 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
279 return ContinueWith<TResult> (continuationFunction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
282 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction, TaskScheduler scheduler)
284 return ContinueWith<TResult> (continuationFunction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
287 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction, CancellationToken cancellationToken,
288 TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
290 if (continuationFunction == null)
291 throw new ArgumentNullException ("continuationFunction");
292 if (scheduler == null)
293 throw new ArgumentNullException ("scheduler");
295 return ContinueWith<TResult> (TaskActionInvoker.Create (continuationFunction), cancellationToken, continuationOptions, scheduler);
298 internal Task<TResult> ContinueWith<TResult> (TaskActionInvoker invoker, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
300 var continuation = new Task<TResult> (invoker, null, cancellationToken, GetCreationOptions (continuationOptions), this);
301 ContinueWithCore (continuation, continuationOptions, scheduler);
306 internal void ContinueWithCore (Task continuation, TaskContinuationOptions options, TaskScheduler scheduler)
308 const TaskContinuationOptions wrongRan = TaskContinuationOptions.NotOnRanToCompletion | TaskContinuationOptions.OnlyOnRanToCompletion;
309 const TaskContinuationOptions wrongCanceled = TaskContinuationOptions.NotOnCanceled | TaskContinuationOptions.OnlyOnCanceled;
310 const TaskContinuationOptions wrongFaulted = TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.OnlyOnFaulted;
312 if (((options & wrongRan) == wrongRan) || ((options & wrongCanceled) == wrongCanceled) || ((options & wrongFaulted) == wrongFaulted))
313 throw new ArgumentException ("continuationOptions", "Some options are mutually exclusive");
315 // Already set the scheduler so that user can call Wait and that sort of stuff
316 continuation.scheduler = scheduler;
317 continuation.Status = TaskStatus.WaitingForActivation;
318 continuation.taskCreationOptions |= TaskCreationOptionsContinuation;
320 ContinueWith (new TaskContinuation (continuation, options));
323 internal void ContinueWith (IContinuation continuation)
326 continuation.Execute ();
330 continuations.Add (continuation);
332 // Retry in case completion was achieved but event adding was too late
334 continuation.Execute ();
337 static internal TaskCreationOptions GetCreationOptions (TaskContinuationOptions kind)
339 TaskCreationOptions options = TaskCreationOptions.None;
340 if ((kind & TaskContinuationOptions.AttachedToParent) > 0)
341 options |= TaskCreationOptions.AttachedToParent;
342 if ((kind & TaskContinuationOptions.PreferFairness) > 0)
343 options |= TaskCreationOptions.PreferFairness;
344 if ((kind & TaskContinuationOptions.LongRunning) > 0)
345 options |= TaskCreationOptions.LongRunning;
350 void RegisterWaitEvent (IEventSlot slot)
357 registeredEvts.Add (slot);
358 if (IsCompleted && registeredEvts.Remove (slot))
362 void UnregisterWaitEvent (IEventSlot slot)
364 registeredEvts.Remove (slot);
368 #region Internal and protected thingies
369 internal void Schedule ()
371 Status = TaskStatus.WaitingToRun;
373 // If worker is null it means it is a local one, revert to the old behavior
374 // If TaskScheduler.Current is not being used, the scheduler was explicitly provided, so we must use that
375 if (scheduler != TaskScheduler.Current || childWorkAdder == null || CheckTaskOptions (taskCreationOptions, TaskCreationOptions.PreferFairness)) {
376 scheduler.QueueTask (this);
378 /* Like the semantic of the ABP paper describe it, we add ourselves to the bottom
379 * of our Parent Task's ThreadWorker deque. It's ok to do that since we are in
380 * the correct Thread during the creation
382 childWorkAdder (this);
388 /* Allow scheduler to break fairness of deque ordering without
389 * breaking its semantic (the task can be executed twice but the
390 * second time it will return immediately
392 if (!executing.TryRelaxedSet ())
395 // Disable CancellationToken direct cancellation
396 if (cancellationRegistration != null) {
397 cancellationRegistration.Value.Dispose ();
398 cancellationRegistration = null;
401 TaskScheduler.Current = scheduler;
403 if (!token.IsCancellationRequested) {
405 status = TaskStatus.Running;
409 } catch (OperationCanceledException oce) {
410 if (token != CancellationToken.None && oce.CancellationToken == token)
413 HandleGenericException (oce);
414 } catch (Exception e) {
415 HandleGenericException (e);
424 internal void Execute (Action<Task> childAdder)
426 childWorkAdder = childAdder;
430 internal void AddChild ()
432 if (childTasks == null)
433 Interlocked.CompareExchange (ref childTasks, new CountdownEvent (1), null);
434 childTasks.AddCount ();
437 internal void ChildCompleted (AggregateException childEx)
439 if (childEx != null) {
440 if (childExceptions == null)
441 Interlocked.CompareExchange (ref childExceptions, new ConcurrentQueue<AggregateException> (), null);
442 childExceptions.Enqueue (childEx);
445 if (childTasks.Signal () && status == TaskStatus.WaitingForChildrenToComplete) {
446 Status = TaskStatus.RanToCompletion;
447 ProcessChildExceptions ();
448 ProcessCompleteDelegates ();
454 if (IsContinuation) {
455 invoker.Invoke (parent, state, this);
457 invoker.Invoke (this, state, this);
461 internal void Finish ()
463 // If there was children created and they all finished, we set the countdown
464 if (childTasks != null)
465 childTasks.Signal ();
467 // Don't override Canceled or Faulted
468 if (status == TaskStatus.Running) {
469 if (childTasks == null || childTasks.IsSet)
470 Status = TaskStatus.RanToCompletion;
472 Status = TaskStatus.WaitingForChildrenToComplete;
475 // Completions are already processed when task is canceled
476 if (status == TaskStatus.RanToCompletion || status == TaskStatus.Faulted)
477 ProcessCompleteDelegates ();
479 // Reset the current thingies
481 TaskScheduler.Current = null;
483 if (cancellationRegistration.HasValue)
484 cancellationRegistration.Value.Dispose ();
486 // Tell parent that we are finished
487 if (CheckTaskOptions (taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null) {
488 parent.ChildCompleted (this.Exception);
492 void ProcessCompleteDelegates ()
494 if (continuations.HasElements) {
495 IContinuation continuation;
496 while (continuations.TryGetNextCompletion (out continuation))
497 continuation.Execute ();
499 if (registeredEvts.HasElements) {
501 while (registeredEvts.TryGetNextCompletion (out evt))
506 void ProcessChildExceptions ()
508 if (childExceptions == null)
511 if (exception == null)
512 exception = new AggregateException ();
514 AggregateException childEx;
515 while (childExceptions.TryDequeue (out childEx))
516 exception.AddChildException (childEx);
520 #region Cancel and Wait related method
522 internal void CancelReal ()
524 Status = TaskStatus.Canceled;
525 ProcessCompleteDelegates ();
528 internal void HandleGenericException (Exception e)
530 HandleGenericException (new AggregateException (e));
533 internal void HandleGenericException (AggregateException e)
536 Thread.MemoryBarrier ();
537 Status = TaskStatus.Faulted;
538 if (scheduler != null && scheduler.FireUnobservedEvent (exception).Observed)
539 exceptionObserved = true;
544 Wait (Timeout.Infinite, CancellationToken.None);
547 public void Wait (CancellationToken cancellationToken)
549 Wait (Timeout.Infinite, cancellationToken);
552 public bool Wait (TimeSpan timeout)
554 return Wait (CheckTimeout (timeout), CancellationToken.None);
557 public bool Wait (int millisecondsTimeout)
559 return Wait (millisecondsTimeout, CancellationToken.None);
562 public bool Wait (int millisecondsTimeout, CancellationToken cancellationToken)
564 if (millisecondsTimeout < -1)
565 throw new ArgumentOutOfRangeException ("millisecondsTimeout");
570 // If the task is ready to be run and we were supposed to wait on it indefinitely, just run it
571 if (Status == TaskStatus.WaitingToRun && millisecondsTimeout == -1 && scheduler != null)
575 var evt = new ManualResetEventSlim ();
576 var slot = new ManualEventSlot (evt);
578 RegisterWaitEvent (slot);
579 result = evt.Wait (millisecondsTimeout, cancellationToken);
582 UnregisterWaitEvent (slot);
589 throw new AggregateException (new TaskCanceledException (this));
591 if (exception != null)
597 public static void WaitAll (params Task[] tasks)
599 WaitAll (tasks, Timeout.Infinite, CancellationToken.None);
602 public static void WaitAll (Task[] tasks, CancellationToken cancellationToken)
604 WaitAll (tasks, Timeout.Infinite, cancellationToken);
607 public static bool WaitAll (Task[] tasks, TimeSpan timeout)
609 return WaitAll (tasks, CheckTimeout (timeout), CancellationToken.None);
612 public static bool WaitAll (Task[] tasks, int millisecondsTimeout)
614 return WaitAll (tasks, millisecondsTimeout, CancellationToken.None);
617 public static bool WaitAll (Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
620 throw new ArgumentNullException ("tasks");
623 foreach (var t in tasks) {
625 throw new ArgumentNullException ("tasks", "the tasks argument contains a null element");
627 result &= t.Status == TaskStatus.RanToCompletion;
631 var evt = new CountdownEvent (tasks.Length);
632 var slot = new CountdownEventSlot (evt);
634 foreach (var t in tasks)
635 t.RegisterWaitEvent (slot);
637 result = evt.Wait (millisecondsTimeout, cancellationToken);
639 List<Exception> exceptions = null;
641 foreach (var t in tasks) {
643 if (t.Status == TaskStatus.RanToCompletion)
645 if (exceptions == null)
646 exceptions = new List<Exception> ();
647 if (t.Exception != null)
648 exceptions.AddRange (t.Exception.InnerExceptions);
650 exceptions.Add (new TaskCanceledException (t));
652 t.UnregisterWaitEvent (slot);
658 if (exceptions != null)
659 throw new AggregateException (exceptions);
666 public static int WaitAny (params Task[] tasks)
668 return WaitAny (tasks, Timeout.Infinite, CancellationToken.None);
671 public static int WaitAny (Task[] tasks, TimeSpan timeout)
673 return WaitAny (tasks, CheckTimeout (timeout));
676 public static int WaitAny (Task[] tasks, int millisecondsTimeout)
678 return WaitAny (tasks, millisecondsTimeout, CancellationToken.None);
681 public static int WaitAny (Task[] tasks, CancellationToken cancellationToken)
683 return WaitAny (tasks, Timeout.Infinite, cancellationToken);
686 public static int WaitAny (Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
689 throw new ArgumentNullException ("tasks");
690 if (millisecondsTimeout < -1)
691 throw new ArgumentOutOfRangeException ("millisecondsTimeout");
692 CheckForNullTasks (tasks);
694 if (tasks.Length > 0) {
695 var evt = new ManualResetEventSlim ();
696 var slot = new ManualEventSlot (evt);
699 for (int i = 0; i < tasks.Length; i++) {
703 t.RegisterWaitEvent (slot);
706 if (!(result = evt.Wait (millisecondsTimeout, cancellationToken)))
710 foreach (var t in tasks)
711 t.UnregisterWaitEvent (slot);
716 int firstFinished = -1;
717 for (int i = 0; i < tasks.Length; i++) {
725 return firstFinished;
728 static int CheckTimeout (TimeSpan timeout)
731 return checked ((int)timeout.TotalMilliseconds);
732 } catch (System.OverflowException) {
733 throw new ArgumentOutOfRangeException ("timeout");
737 static void CheckForNullTasks (Task[] tasks)
739 foreach (var t in tasks)
741 throw new ArgumentNullException ("tasks", "the tasks argument contains a null element");
746 public void Dispose ()
751 protected virtual void Dispose (bool disposing)
754 throw new InvalidOperationException ("A task may only be disposed if it is in a completion state");
756 // Set action to null so that the GC can collect the delegate and thus
757 // any big object references that the user might have captured in a anonymous method
761 if (cancellationRegistration != null)
762 cancellationRegistration.Value.Dispose ();
769 public ConfiguredTaskAwaitable ConfigureAwait (bool continueOnCapturedContext)
771 return new ConfiguredTaskAwaitable (this, continueOnCapturedContext);
774 public Task ContinueWith (Action<Task, object> continuationAction, object state)
776 return ContinueWith (continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
779 public Task ContinueWith (Action<Task, object> continuationAction, object state, CancellationToken cancellationToken)
781 return ContinueWith (continuationAction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
784 public Task ContinueWith (Action<Task, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
786 return ContinueWith (continuationAction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
789 public Task ContinueWith (Action<Task, object> continuationAction, object state, TaskScheduler scheduler)
791 return ContinueWith (continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
794 public Task ContinueWith (Action<Task, object> continuationAction, object state, CancellationToken cancellationToken,
795 TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
797 if (continuationAction == null)
798 throw new ArgumentNullException ("continuationAction");
799 if (scheduler == null)
800 throw new ArgumentNullException ("scheduler");
802 Task continuation = new Task (TaskActionInvoker.Create (continuationAction),
803 state, cancellationToken,
804 GetCreationOptions (continuationOptions),
806 ContinueWithCore (continuation, continuationOptions, scheduler);
811 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state)
813 return ContinueWith<TResult> (continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
816 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
818 return ContinueWith<TResult> (continuationFunction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
821 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken)
823 return ContinueWith<TResult> (continuationFunction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
826 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler)
828 return ContinueWith<TResult> (continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
831 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken,
832 TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
834 if (continuationFunction == null)
835 throw new ArgumentNullException ("continuationFunction");
836 if (scheduler == null)
837 throw new ArgumentNullException ("scheduler");
839 var t = new Task<TResult> (TaskActionInvoker.Create (continuationFunction),
842 GetCreationOptions (continuationOptions),
845 ContinueWithCore (t, continuationOptions, scheduler);
850 public static Task<TResult> FromResult<TResult> (TResult result)
852 var tcs = new TaskCompletionSource<TResult> ();
853 tcs.SetResult (result);
857 public TaskAwaiter GetAwaiter ()
859 return new TaskAwaiter (this);
862 public static Task Run (Action action)
864 return Run (action, CancellationToken.None);
867 public static Task Run (Action action, CancellationToken cancellationToken)
869 if (cancellationToken.IsCancellationRequested)
870 return TaskConstants.Canceled;
872 var t = new Task (action, cancellationToken, TaskCreationOptions.DenyChildAttach);
877 public static Task Run (Func<Task> function)
879 return Run (function, CancellationToken.None);
882 public static Task Run (Func<Task> function, CancellationToken cancellationToken)
884 if (cancellationToken.IsCancellationRequested)
885 return TaskConstants.Canceled;
887 var t = new Task<Task> (function, cancellationToken);
892 public static Task<TResult> Run<TResult> (Func<TResult> function)
894 return Run (function, CancellationToken.None);
897 public static Task<TResult> Run<TResult> (Func<TResult> function, CancellationToken cancellationToken)
899 if (cancellationToken.IsCancellationRequested)
900 return TaskConstants<TResult>.Canceled;
902 var t = new Task<TResult> (function, cancellationToken, TaskCreationOptions.DenyChildAttach);
907 public static Task<TResult> Run<TResult> (Func<Task<TResult>> function)
909 return Run (function, CancellationToken.None);
912 public static Task<TResult> Run<TResult> (Func<Task<TResult>> function, CancellationToken cancellationToken)
914 if (cancellationToken.IsCancellationRequested)
915 return TaskConstants<TResult>.Canceled;
917 var t = Task<Task<TResult>>.Factory.StartNew (function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
918 return GetTaskResult (t);
921 async static Task<TResult> GetTaskResult<TResult> (Task<Task<TResult>> task)
923 var r = await task.ConfigureAwait (false);
927 public static YieldAwaitable Yield ()
929 return new YieldAwaitable ();
934 public static TaskFactory Factory {
936 return defaultFactory;
940 public static int? CurrentId {
943 return t == null ? (int?)null : t.Id;
947 public AggregateException Exception {
949 exceptionObserved = true;
958 public bool IsCanceled {
960 return status == TaskStatus.Canceled;
964 public bool IsCompleted {
966 return status >= TaskStatus.RanToCompletion;
970 public bool IsFaulted {
972 return status == TaskStatus.Faulted;
976 public TaskCreationOptions CreationOptions {
978 return taskCreationOptions & MaxTaskCreationOptions;
982 public TaskStatus Status {
988 Thread.MemoryBarrier ();
992 public object AsyncState {
998 bool IAsyncResult.CompletedSynchronously {
1004 WaitHandle IAsyncResult.AsyncWaitHandle {
1016 bool IsContinuation {
1018 return (taskCreationOptions & TaskCreationOptionsContinuation) != 0;
1022 internal Task Parent {
1028 internal string DisplayActionMethod {
1030 Delegate d = invoker.Action;
1031 return d == null ? "<none>" : d.Method.ToString ();