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 TaskExceptionSlot exSlot;
70 TaskActionInvoker invoker;
72 internal AtomicBooleanValue executing;
74 TaskCompletionQueue<IContinuation> continuations;
76 CancellationToken token;
77 CancellationTokenRegistration? cancellationRegistration;
79 internal const TaskCreationOptions WorkerTaskNotSupportedOptions = TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness;
81 const TaskCreationOptions MaxTaskCreationOptions =
83 TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler |
85 TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent;
87 public Task (Action action)
88 : this (action, TaskCreationOptions.None)
93 public Task (Action action, TaskCreationOptions creationOptions)
94 : this (action, CancellationToken.None, creationOptions)
99 public Task (Action action, CancellationToken cancellationToken)
100 : this (action, cancellationToken, TaskCreationOptions.None)
105 public Task (Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
106 : this (TaskActionInvoker.Create (action), null, cancellationToken, creationOptions, current)
109 throw new ArgumentNullException ("action");
110 if (creationOptions > MaxTaskCreationOptions || creationOptions < TaskCreationOptions.None)
111 throw new ArgumentOutOfRangeException ("creationOptions");
114 public Task (Action<object> action, object state)
115 : this (action, state, TaskCreationOptions.None)
119 public Task (Action<object> action, object state, TaskCreationOptions creationOptions)
120 : this (action, state, CancellationToken.None, creationOptions)
124 public Task (Action<object> action, object state, CancellationToken cancellationToken)
125 : this (action, state, cancellationToken, TaskCreationOptions.None)
129 public Task (Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
130 : this (TaskActionInvoker.Create (action), state, cancellationToken, creationOptions, current)
133 throw new ArgumentNullException ("action");
134 if (creationOptions > MaxTaskCreationOptions || creationOptions < TaskCreationOptions.None)
135 throw new ArgumentOutOfRangeException ("creationOptions");
138 internal Task (TaskActionInvoker invoker, object state, CancellationToken cancellationToken,
139 TaskCreationOptions creationOptions, Task parent)
141 this.invoker = invoker;
142 this.taskCreationOptions = creationOptions;
144 this.taskId = Interlocked.Increment (ref id);
145 this.status = cancellationToken.IsCancellationRequested ? TaskStatus.Canceled : TaskStatus.Created;
146 this.token = cancellationToken;
147 this.parent = parent;
149 // Process taskCreationOptions
150 if (CheckTaskOptions (taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null)
153 if (token.CanBeCanceled)
154 cancellationRegistration = token.Register (l => ((Task) l).CancelReal (), this);
157 bool CheckTaskOptions (TaskCreationOptions opt, TaskCreationOptions member)
159 return (opt & member) == member;
165 Start (TaskScheduler.Current);
168 public void Start (TaskScheduler scheduler)
170 if (scheduler == null)
171 throw new ArgumentNullException ("scheduler");
173 if (status >= TaskStatus.WaitingToRun)
174 throw new InvalidOperationException ("The Task is not in a valid state to be started.");
177 throw new InvalidOperationException ("Start may not be called on a continuation task");
179 SetupScheduler (scheduler);
183 internal void SetupScheduler (TaskScheduler scheduler)
185 this.scheduler = scheduler;
186 Status = TaskStatus.WaitingForActivation;
189 public void RunSynchronously ()
191 RunSynchronously (TaskScheduler.Current);
194 public void RunSynchronously (TaskScheduler scheduler)
196 if (scheduler == null)
197 throw new ArgumentNullException ("scheduler");
199 if (Status > TaskStatus.WaitingForActivation)
200 throw new InvalidOperationException ("The task is not in a valid state to be started");
202 SetupScheduler (scheduler);
203 var saveStatus = status;
204 Status = TaskStatus.WaitingToRun;
207 if (scheduler.RunInline (this))
209 } catch (Exception inner) {
210 throw new TaskSchedulerException (inner);
220 public Task ContinueWith (Action<Task> continuationAction)
222 return ContinueWith (continuationAction, TaskContinuationOptions.None);
225 public Task ContinueWith (Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
227 return ContinueWith (continuationAction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
230 public Task ContinueWith (Action<Task> continuationAction, CancellationToken cancellationToken)
232 return ContinueWith (continuationAction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
235 public Task ContinueWith (Action<Task> continuationAction, TaskScheduler scheduler)
237 return ContinueWith (continuationAction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
240 public Task ContinueWith (Action<Task> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
242 if (continuationAction == null)
243 throw new ArgumentNullException ("continuationAction");
244 if (scheduler == null)
245 throw new ArgumentNullException ("scheduler");
247 return ContinueWith (TaskActionInvoker.Create (continuationAction), cancellationToken, continuationOptions, scheduler);
250 internal Task ContinueWith (TaskActionInvoker invoker, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
252 var continuation = new Task (invoker, null, cancellationToken, GetCreationOptions (continuationOptions), this);
253 ContinueWithCore (continuation, continuationOptions, scheduler);
258 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction)
260 return ContinueWith<TResult> (continuationFunction, TaskContinuationOptions.None);
263 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
265 return ContinueWith<TResult> (continuationFunction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
268 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
270 return ContinueWith<TResult> (continuationFunction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
273 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction, TaskScheduler scheduler)
275 return ContinueWith<TResult> (continuationFunction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
278 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction, CancellationToken cancellationToken,
279 TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
281 if (continuationFunction == null)
282 throw new ArgumentNullException ("continuationFunction");
283 if (scheduler == null)
284 throw new ArgumentNullException ("scheduler");
286 return ContinueWith<TResult> (TaskActionInvoker.Create (continuationFunction), cancellationToken, continuationOptions, scheduler);
289 internal Task<TResult> ContinueWith<TResult> (TaskActionInvoker invoker, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
291 var continuation = new Task<TResult> (invoker, null, cancellationToken, GetCreationOptions (continuationOptions), this);
292 ContinueWithCore (continuation, continuationOptions, scheduler);
297 internal void ContinueWithCore (Task continuation, TaskContinuationOptions options, TaskScheduler scheduler)
299 const TaskContinuationOptions wrongRan = TaskContinuationOptions.NotOnRanToCompletion | TaskContinuationOptions.OnlyOnRanToCompletion;
300 const TaskContinuationOptions wrongCanceled = TaskContinuationOptions.NotOnCanceled | TaskContinuationOptions.OnlyOnCanceled;
301 const TaskContinuationOptions wrongFaulted = TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.OnlyOnFaulted;
303 if (((options & wrongRan) == wrongRan) || ((options & wrongCanceled) == wrongCanceled) || ((options & wrongFaulted) == wrongFaulted))
304 throw new ArgumentException ("continuationOptions", "Some options are mutually exclusive");
306 // Already set the scheduler so that user can call Wait and that sort of stuff
307 continuation.scheduler = scheduler;
308 continuation.Status = TaskStatus.WaitingForActivation;
309 continuation.taskCreationOptions |= TaskCreationOptionsContinuation;
311 ContinueWith (new TaskContinuation (continuation, options));
314 internal void ContinueWith (IContinuation continuation)
317 continuation.Execute ();
321 continuations.Add (continuation);
323 // Retry in case completion was achieved but event adding was too late
324 if (IsCompleted && continuations.Remove (continuation))
325 continuation.Execute ();
328 void RemoveContinuation (IContinuation continuation)
330 continuations.Remove (continuation);
333 static internal TaskCreationOptions GetCreationOptions (TaskContinuationOptions kind)
335 TaskCreationOptions options = TaskCreationOptions.None;
336 if ((kind & TaskContinuationOptions.AttachedToParent) > 0)
337 options |= TaskCreationOptions.AttachedToParent;
338 if ((kind & TaskContinuationOptions.PreferFairness) > 0)
339 options |= TaskCreationOptions.PreferFairness;
340 if ((kind & TaskContinuationOptions.LongRunning) > 0)
341 options |= TaskCreationOptions.LongRunning;
347 #region Internal and protected thingies
348 internal void Schedule ()
350 Status = TaskStatus.WaitingToRun;
352 // If worker is null it means it is a local one, revert to the old behavior
353 // If TaskScheduler.Current is not being used, the scheduler was explicitly provided, so we must use that
354 if (scheduler != TaskScheduler.Current || childWorkAdder == null || CheckTaskOptions (taskCreationOptions, TaskCreationOptions.PreferFairness)) {
355 scheduler.QueueTask (this);
357 /* Like the semantic of the ABP paper describe it, we add ourselves to the bottom
358 * of our Parent Task's ThreadWorker deque. It's ok to do that since we are in
359 * the correct Thread during the creation
361 childWorkAdder (this);
367 /* Allow scheduler to break fairness of deque ordering without
368 * breaking its semantic (the task can be executed twice but the
369 * second time it will return immediately
371 if (!executing.TryRelaxedSet ())
374 // Disable CancellationToken direct cancellation
375 if (cancellationRegistration != null) {
376 cancellationRegistration.Value.Dispose ();
377 cancellationRegistration = null;
380 TaskScheduler.Current = scheduler;
382 if (!token.IsCancellationRequested) {
384 status = TaskStatus.Running;
388 } catch (OperationCanceledException oce) {
389 if (token != CancellationToken.None && oce.CancellationToken == token)
392 HandleGenericException (oce);
393 } catch (Exception e) {
394 HandleGenericException (e);
403 internal bool TrySetCanceled ()
408 if (!executing.TryRelaxedSet ()) {
409 var sw = new SpinWait ();
420 internal bool TrySetException (AggregateException aggregate)
425 if (!executing.TryRelaxedSet ()) {
426 var sw = new SpinWait ();
433 HandleGenericException (aggregate);
437 internal void Execute (Action<Task> childAdder)
439 childWorkAdder = childAdder;
443 internal void Execute ()
448 internal void AddChild ()
450 if (childTasks == null)
451 Interlocked.CompareExchange (ref childTasks, new CountdownEvent (1), null);
452 childTasks.AddCount ();
455 internal void ChildCompleted (AggregateException childEx)
457 if (childEx != null) {
458 if (ExceptionSlot.ChildExceptions == null)
459 Interlocked.CompareExchange (ref ExceptionSlot.ChildExceptions, new ConcurrentQueue<AggregateException> (), null);
460 ExceptionSlot.ChildExceptions.Enqueue (childEx);
463 if (childTasks.Signal () && status == TaskStatus.WaitingForChildrenToComplete) {
464 Status = TaskStatus.RanToCompletion;
465 ProcessChildExceptions ();
466 ProcessCompleteDelegates ();
472 if (IsContinuation) {
473 invoker.Invoke (parent, state, this);
475 invoker.Invoke (this, state, this);
479 internal void Finish ()
481 // If there was children created and they all finished, we set the countdown
482 if (childTasks != null)
483 childTasks.Signal ();
485 // Don't override Canceled or Faulted
486 if (status == TaskStatus.Running) {
487 if (childTasks == null || childTasks.IsSet)
488 Status = TaskStatus.RanToCompletion;
490 Status = TaskStatus.WaitingForChildrenToComplete;
493 // Completions are already processed when task is canceled or faulted
494 if (status == TaskStatus.RanToCompletion)
495 ProcessCompleteDelegates ();
497 // Reset the current thingies
499 TaskScheduler.Current = null;
501 if (cancellationRegistration.HasValue)
502 cancellationRegistration.Value.Dispose ();
504 // Tell parent that we are finished
505 if (CheckTaskOptions (taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null) {
506 parent.ChildCompleted (this.Exception);
510 void ProcessCompleteDelegates ()
512 if (continuations.HasElements) {
513 IContinuation continuation;
514 while (continuations.TryGetNextCompletion (out continuation))
515 continuation.Execute ();
519 void ProcessChildExceptions ()
521 if (exSlot == null || exSlot.ChildExceptions == null)
524 if (ExceptionSlot.Exception == null)
525 exSlot.Exception = new AggregateException ();
527 AggregateException childEx;
528 while (exSlot.ChildExceptions.TryDequeue (out childEx))
529 exSlot.Exception.AddChildException (childEx);
533 #region Cancel and Wait related method
535 internal void CancelReal ()
537 Status = TaskStatus.Canceled;
538 ProcessCompleteDelegates ();
541 void HandleGenericException (Exception e)
543 HandleGenericException (new AggregateException (e));
546 void HandleGenericException (AggregateException e)
548 ExceptionSlot.Exception = e;
549 Thread.MemoryBarrier ();
550 Status = TaskStatus.Faulted;
551 ProcessCompleteDelegates ();
556 Wait (Timeout.Infinite, CancellationToken.None);
559 public void Wait (CancellationToken cancellationToken)
561 Wait (Timeout.Infinite, cancellationToken);
564 public bool Wait (TimeSpan timeout)
566 return Wait (CheckTimeout (timeout), CancellationToken.None);
569 public bool Wait (int millisecondsTimeout)
571 return Wait (millisecondsTimeout, CancellationToken.None);
574 public bool Wait (int millisecondsTimeout, CancellationToken cancellationToken)
576 if (millisecondsTimeout < -1)
577 throw new ArgumentOutOfRangeException ("millisecondsTimeout");
582 // If the task is ready to be run and we were supposed to wait on it indefinitely, just run it
583 if (Status == TaskStatus.WaitingToRun && millisecondsTimeout == -1 && scheduler != null)
587 var evt = new ManualResetEventSlim ();
588 var slot = new ManualEventSlot (evt);
591 result = evt.Wait (millisecondsTimeout, cancellationToken);
594 RemoveContinuation (slot);
601 throw new AggregateException (new TaskCanceledException (this));
603 var exception = Exception;
604 if (exception != null)
610 public static void WaitAll (params Task[] tasks)
612 WaitAll (tasks, Timeout.Infinite, CancellationToken.None);
615 public static void WaitAll (Task[] tasks, CancellationToken cancellationToken)
617 WaitAll (tasks, Timeout.Infinite, cancellationToken);
620 public static bool WaitAll (Task[] tasks, TimeSpan timeout)
622 return WaitAll (tasks, CheckTimeout (timeout), CancellationToken.None);
625 public static bool WaitAll (Task[] tasks, int millisecondsTimeout)
627 return WaitAll (tasks, millisecondsTimeout, CancellationToken.None);
630 public static bool WaitAll (Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
633 throw new ArgumentNullException ("tasks");
636 foreach (var t in tasks) {
638 throw new ArgumentNullException ("tasks", "the tasks argument contains a null element");
640 result &= t.Status == TaskStatus.RanToCompletion;
644 var evt = new CountdownEvent (tasks.Length);
645 var slot = new CountdownEventSlot (evt);
647 foreach (var t in tasks)
648 t.ContinueWith (slot);
650 result = evt.Wait (millisecondsTimeout, cancellationToken);
652 List<Exception> exceptions = null;
654 foreach (var t in tasks) {
656 if (t.Status == TaskStatus.RanToCompletion)
658 if (exceptions == null)
659 exceptions = new List<Exception> ();
660 if (t.Exception != null)
661 exceptions.AddRange (t.Exception.InnerExceptions);
663 exceptions.Add (new TaskCanceledException (t));
665 t.RemoveContinuation (slot);
671 if (exceptions != null)
672 throw new AggregateException (exceptions);
679 public static int WaitAny (params Task[] tasks)
681 return WaitAny (tasks, Timeout.Infinite, CancellationToken.None);
684 public static int WaitAny (Task[] tasks, TimeSpan timeout)
686 return WaitAny (tasks, CheckTimeout (timeout));
689 public static int WaitAny (Task[] tasks, int millisecondsTimeout)
691 return WaitAny (tasks, millisecondsTimeout, CancellationToken.None);
694 public static int WaitAny (Task[] tasks, CancellationToken cancellationToken)
696 return WaitAny (tasks, Timeout.Infinite, cancellationToken);
699 public static int WaitAny (Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
702 throw new ArgumentNullException ("tasks");
703 if (millisecondsTimeout < -1)
704 throw new ArgumentOutOfRangeException ("millisecondsTimeout");
705 CheckForNullTasks (tasks);
707 if (tasks.Length > 0) {
708 var evt = new ManualResetEventSlim ();
709 var slot = new ManualEventSlot (evt);
712 for (int i = 0; i < tasks.Length; i++) {
716 t.ContinueWith (slot);
719 if (!(result = evt.Wait (millisecondsTimeout, cancellationToken)))
723 foreach (var t in tasks)
724 t.RemoveContinuation (slot);
729 int firstFinished = -1;
730 for (int i = 0; i < tasks.Length; i++) {
738 return firstFinished;
741 static int CheckTimeout (TimeSpan timeout)
744 return checked ((int)timeout.TotalMilliseconds);
745 } catch (System.OverflowException) {
746 throw new ArgumentOutOfRangeException ("timeout");
750 static void CheckForNullTasks (Task[] tasks)
752 foreach (var t in tasks)
754 throw new ArgumentNullException ("tasks", "the tasks argument contains a null element");
759 public void Dispose ()
764 protected virtual void Dispose (bool disposing)
767 throw new InvalidOperationException ("A task may only be disposed if it is in a completion state");
769 // Set action to null so that the GC can collect the delegate and thus
770 // any big object references that the user might have captured in a anonymous method
774 if (cancellationRegistration != null)
775 cancellationRegistration.Value.Dispose ();
782 public ConfiguredTaskAwaitable ConfigureAwait (bool continueOnCapturedContext)
784 return new ConfiguredTaskAwaitable (this, continueOnCapturedContext);
787 public Task ContinueWith (Action<Task, object> continuationAction, object state)
789 return ContinueWith (continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
792 public Task ContinueWith (Action<Task, object> continuationAction, object state, CancellationToken cancellationToken)
794 return ContinueWith (continuationAction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
797 public Task ContinueWith (Action<Task, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
799 return ContinueWith (continuationAction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
802 public Task ContinueWith (Action<Task, object> continuationAction, object state, TaskScheduler scheduler)
804 return ContinueWith (continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
807 public Task ContinueWith (Action<Task, object> continuationAction, object state, CancellationToken cancellationToken,
808 TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
810 if (continuationAction == null)
811 throw new ArgumentNullException ("continuationAction");
812 if (scheduler == null)
813 throw new ArgumentNullException ("scheduler");
815 Task continuation = new Task (TaskActionInvoker.Create (continuationAction),
816 state, cancellationToken,
817 GetCreationOptions (continuationOptions),
819 ContinueWithCore (continuation, continuationOptions, scheduler);
824 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state)
826 return ContinueWith<TResult> (continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
829 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
831 return ContinueWith<TResult> (continuationFunction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
834 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken)
836 return ContinueWith<TResult> (continuationFunction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
839 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler)
841 return ContinueWith<TResult> (continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
844 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken,
845 TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
847 if (continuationFunction == null)
848 throw new ArgumentNullException ("continuationFunction");
849 if (scheduler == null)
850 throw new ArgumentNullException ("scheduler");
852 var t = new Task<TResult> (TaskActionInvoker.Create (continuationFunction),
855 GetCreationOptions (continuationOptions),
858 ContinueWithCore (t, continuationOptions, scheduler);
863 public static Task<TResult> FromResult<TResult> (TResult result)
865 var tcs = new TaskCompletionSource<TResult> ();
866 tcs.SetResult (result);
870 public TaskAwaiter GetAwaiter ()
872 return new TaskAwaiter (this);
875 public static Task Run (Action action)
877 return Run (action, CancellationToken.None);
880 public static Task Run (Action action, CancellationToken cancellationToken)
882 if (cancellationToken.IsCancellationRequested)
883 return TaskConstants.Canceled;
885 var t = new Task (action, cancellationToken, TaskCreationOptions.DenyChildAttach);
890 public static Task Run (Func<Task> function)
892 return Run (function, CancellationToken.None);
895 public static Task Run (Func<Task> function, CancellationToken cancellationToken)
897 if (cancellationToken.IsCancellationRequested)
898 return TaskConstants.Canceled;
900 var t = new Task<Task> (function, cancellationToken);
905 public static Task<TResult> Run<TResult> (Func<TResult> function)
907 return Run (function, CancellationToken.None);
910 public static Task<TResult> Run<TResult> (Func<TResult> function, CancellationToken cancellationToken)
912 if (cancellationToken.IsCancellationRequested)
913 return TaskConstants<TResult>.Canceled;
915 var t = new Task<TResult> (function, cancellationToken, TaskCreationOptions.DenyChildAttach);
920 public static Task<TResult> Run<TResult> (Func<Task<TResult>> function)
922 return Run (function, CancellationToken.None);
925 public static Task<TResult> Run<TResult> (Func<Task<TResult>> function, CancellationToken cancellationToken)
927 if (cancellationToken.IsCancellationRequested)
928 return TaskConstants<TResult>.Canceled;
930 var t = Task<Task<TResult>>.Factory.StartNew (function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
931 return GetTaskResult (t);
934 async static Task<TResult> GetTaskResult<TResult> (Task<Task<TResult>> task)
936 var r = await task.ConfigureAwait (false);
940 public static YieldAwaitable Yield ()
942 return new YieldAwaitable ();
947 public static TaskFactory Factory {
949 return defaultFactory;
953 public static int? CurrentId {
956 return t == null ? (int?)null : t.Id;
960 public AggregateException Exception {
964 exSlot.Observed = true;
965 return exSlot.Exception;
968 ExceptionSlot.Exception = value;
972 public bool IsCanceled {
974 return status == TaskStatus.Canceled;
978 public bool IsCompleted {
980 return status >= TaskStatus.RanToCompletion;
984 public bool IsFaulted {
986 return status == TaskStatus.Faulted;
990 public TaskCreationOptions CreationOptions {
992 return taskCreationOptions & MaxTaskCreationOptions;
996 public TaskStatus Status {
1002 Thread.MemoryBarrier ();
1006 TaskExceptionSlot ExceptionSlot {
1010 Interlocked.CompareExchange (ref exSlot, new TaskExceptionSlot (this), null);
1015 public object AsyncState {
1021 bool IAsyncResult.CompletedSynchronously {
1027 WaitHandle IAsyncResult.AsyncWaitHandle {
1039 bool IsContinuation {
1041 return (taskCreationOptions & TaskCreationOptionsContinuation) != 0;
1045 internal Task Parent {
1051 internal string DisplayActionMethod {
1053 Delegate d = invoker.Action;
1054 return d == null ? "<none>" : d.Method.ToString ();