5 // Marek Safar <marek.safar@gmail.com>
7 // Copyright (c) 2008 Jérémie "Garuma" Laval
8 // Copyright 2011 Xamarin Inc (http://www.xamarin.com).
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
33 using System.Threading;
34 using System.Collections.Concurrent;
35 using System.Collections.Generic;
36 using System.Runtime.CompilerServices;
38 namespace System.Threading.Tasks
40 [System.Diagnostics.DebuggerDisplay ("Id = {Id}, Status = {Status}")]
41 [System.Diagnostics.DebuggerTypeProxy (typeof (TaskDebuggerView))]
42 public class Task : IDisposable, IAsyncResult
44 // With this attribute each thread has its own value so that it's correct for our Schedule code
45 // and for Parent property.
49 static Action<Task> childWorkAdder;
54 static readonly TaskFactory defaultFactory = new TaskFactory ();
55 static readonly Watch watch = Watch.StartNew ();
57 CountdownEvent childTasks;
60 TaskCreationOptions taskCreationOptions;
62 TaskScheduler scheduler;
64 ManualResetEventSlim schedWait = new ManualResetEventSlim (false);
66 volatile AggregateException exception;
67 volatile bool exceptionObserved;
68 ConcurrentQueue<AggregateException> childExceptions;
72 Action<object> action;
75 AtomicBooleanValue executing;
77 TaskCompletionQueue<Task> completed;
78 TaskCompletionQueue<ManualResetEventSlim> registeredEvts;
79 // If this task is a continuation, this stuff gets filled
82 CancellationToken token;
83 CancellationTokenRegistration? cancellationRegistration;
85 internal const TaskCreationOptions WorkerTaskNotSupportedOptions = TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness;
87 const TaskCreationOptions MaxTaskCreationOptions =
89 TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler |
91 TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent;
93 public Task (Action action) : this (action, TaskCreationOptions.None)
98 public Task (Action action, TaskCreationOptions creationOptions) : this (action, CancellationToken.None, creationOptions)
103 public Task (Action action, CancellationToken cancellationToken) : this (action, cancellationToken, TaskCreationOptions.None)
108 public Task (Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
109 : this (null, null, cancellationToken, creationOptions, current)
112 throw new ArgumentNullException ("action");
113 if (creationOptions > MaxTaskCreationOptions || creationOptions < TaskCreationOptions.None)
114 throw new ArgumentOutOfRangeException ("creationOptions");
115 this.simpleAction = action;
118 public Task (Action<object> action, object state) : 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 (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 (Action<object> action,
143 CancellationToken cancellationToken,
144 TaskCreationOptions creationOptions,
147 this.taskCreationOptions = creationOptions;
148 this.action = action;
150 this.taskId = Interlocked.Increment (ref id);
151 this.status = cancellationToken.IsCancellationRequested ? TaskStatus.Canceled : TaskStatus.Created;
152 this.token = cancellationToken;
153 this.parent = parent;
155 // Process taskCreationOptions
156 if (CheckTaskOptions (taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null)
159 if (token.CanBeCanceled)
160 cancellationRegistration = token.Register (l => ((Task) l).CancelReal (), this);
165 if (exception != null && !exceptionObserved)
169 bool CheckTaskOptions (TaskCreationOptions opt, TaskCreationOptions member)
171 return (opt & member) == member;
177 Start (TaskScheduler.Current);
180 public void Start (TaskScheduler scheduler)
182 if (scheduler == null)
183 throw new ArgumentNullException ("scheduler");
185 if (status >= TaskStatus.WaitingToRun)
186 throw new InvalidOperationException ("The Task is not in a valid state to be started.");
188 if (Slot.Initialized)
189 throw new InvalidOperationException ("Start may not be called on a continuation task");
191 SetupScheduler (scheduler);
195 internal void SetupScheduler (TaskScheduler scheduler)
197 this.scheduler = scheduler;
198 status = TaskStatus.WaitingForActivation;
202 public void RunSynchronously ()
204 RunSynchronously (TaskScheduler.Current);
207 public void RunSynchronously (TaskScheduler scheduler)
209 if (scheduler == null)
210 throw new ArgumentNullException ("scheduler");
212 if (Status > TaskStatus.WaitingForActivation)
213 throw new InvalidOperationException ("The task is not in a valid state to be started");
215 SetupScheduler (scheduler);
216 var saveStatus = status;
217 status = TaskStatus.WaitingToRun;
220 if (scheduler.RunInline (this))
222 } catch (Exception inner) {
223 throw new TaskSchedulerException (inner);
233 public Task ContinueWith (Action<Task> continuationAction)
235 return ContinueWith (continuationAction, TaskContinuationOptions.None);
238 public Task ContinueWith (Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
240 return ContinueWith (continuationAction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
243 public Task ContinueWith (Action<Task> continuationAction, CancellationToken cancellationToken)
245 return ContinueWith (continuationAction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
248 public Task ContinueWith (Action<Task> continuationAction, TaskScheduler scheduler)
250 return ContinueWith (continuationAction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
253 public Task ContinueWith (Action<Task> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
255 if (continuationAction == null)
256 throw new ArgumentNullException ("continuationAction");
257 if (scheduler == null)
258 throw new ArgumentNullException ("scheduler");
260 Task continuation = new Task (l => continuationAction ((Task)l),
263 GetCreationOptions (continuationOptions),
265 ContinueWithCore (continuation, continuationOptions, scheduler);
270 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction)
272 return ContinueWith<TResult> (continuationFunction, TaskContinuationOptions.None);
275 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
277 return ContinueWith<TResult> (continuationFunction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
280 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
282 return ContinueWith<TResult> (continuationFunction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
285 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction, TaskScheduler scheduler)
287 return ContinueWith<TResult> (continuationFunction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
290 public Task<TResult> ContinueWith<TResult> (Func<Task, TResult> continuationFunction, CancellationToken cancellationToken,
291 TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
293 if (continuationFunction == null)
294 throw new ArgumentNullException ("continuationFunction");
295 if (scheduler == null)
296 throw new ArgumentNullException ("scheduler");
298 Task<TResult> t = new Task<TResult> ((o) => continuationFunction ((Task)o),
301 GetCreationOptions (continuationOptions),
304 ContinueWithCore (t, continuationOptions, scheduler);
309 internal void ContinueWithCore (Task continuation, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
311 ContinueWithCore (continuation, continuationOptions, scheduler, null);
314 internal void ContinueWithCore (Task continuation, TaskContinuationOptions kind,
315 TaskScheduler scheduler, Func<bool> predicate)
317 // Already set the scheduler so that user can call Wait and that sort of stuff
318 continuation.scheduler = scheduler;
319 continuation.schedWait.Set ();
320 continuation.status = TaskStatus.WaitingForActivation;
321 continuation.Slot = new CompletionSlot (kind, predicate);
324 CompletionExecutor (continuation);
328 completed.Add (continuation);
330 // Retry in case completion was achieved but event adding was too late
332 CompletionExecutor (continuation);
335 bool ContinuationStatusCheck (TaskContinuationOptions kind)
337 if (kind == TaskContinuationOptions.None)
340 int kindCode = (int)kind;
342 if (kindCode >= ((int)TaskContinuationOptions.NotOnRanToCompletion)) {
343 // Remove other options
344 kind &= ~(TaskContinuationOptions.PreferFairness
345 | TaskContinuationOptions.LongRunning
346 | TaskContinuationOptions.AttachedToParent
347 | TaskContinuationOptions.ExecuteSynchronously);
349 if (status == TaskStatus.Canceled) {
350 if (kind == TaskContinuationOptions.NotOnCanceled)
352 if (kind == TaskContinuationOptions.OnlyOnFaulted)
354 if (kind == TaskContinuationOptions.OnlyOnRanToCompletion)
356 } else if (status == TaskStatus.Faulted) {
357 if (kind == TaskContinuationOptions.NotOnFaulted)
359 if (kind == TaskContinuationOptions.OnlyOnCanceled)
361 if (kind == TaskContinuationOptions.OnlyOnRanToCompletion)
363 } else if (status == TaskStatus.RanToCompletion) {
364 if (kind == TaskContinuationOptions.NotOnRanToCompletion)
366 if (kind == TaskContinuationOptions.OnlyOnFaulted)
368 if (kind == TaskContinuationOptions.OnlyOnCanceled)
376 static internal TaskCreationOptions GetCreationOptions (TaskContinuationOptions kind)
378 TaskCreationOptions options = TaskCreationOptions.None;
379 if ((kind & TaskContinuationOptions.AttachedToParent) > 0)
380 options |= TaskCreationOptions.AttachedToParent;
381 if ((kind & TaskContinuationOptions.PreferFairness) > 0)
382 options |= TaskCreationOptions.PreferFairness;
383 if ((kind & TaskContinuationOptions.LongRunning) > 0)
384 options |= TaskCreationOptions.LongRunning;
389 internal void RegisterWaitEvent (ManualResetEventSlim evt)
396 registeredEvts.Add (evt);
402 #region Internal and protected thingies
403 internal void Schedule ()
405 status = TaskStatus.WaitingToRun;
407 // If worker is null it means it is a local one, revert to the old behavior
408 // If TaskScheduler.Current is not being used, the scheduler was explicitly provided, so we must use that
409 if (scheduler != TaskScheduler.Current || childWorkAdder == null || CheckTaskOptions (taskCreationOptions, TaskCreationOptions.PreferFairness)) {
410 scheduler.QueueTask (this);
412 /* Like the semantic of the ABP paper describe it, we add ourselves to the bottom
413 * of our Parent Task's ThreadWorker deque. It's ok to do that since we are in
414 * the correct Thread during the creation
416 childWorkAdder (this);
422 /* Allow scheduler to break fairness of deque ordering without
423 * breaking its semantic (the task can be executed twice but the
424 * second time it will return immediately
426 if (!executing.TryRelaxedSet ())
429 // Disable CancellationToken direct cancellation
430 if (cancellationRegistration != null) {
431 cancellationRegistration.Value.Dispose ();
432 cancellationRegistration = null;
435 TaskScheduler.Current = scheduler;
437 if (!token.IsCancellationRequested) {
439 status = TaskStatus.Running;
443 } catch (OperationCanceledException oce) {
444 if (token != CancellationToken.None && oce.CancellationToken == token)
447 HandleGenericException (oce);
448 } catch (Exception e) {
449 HandleGenericException (e);
458 internal void Execute (Action<Task> childAdder)
460 childWorkAdder = childAdder;
464 internal void AddChild ()
466 if (childTasks == null)
467 Interlocked.CompareExchange (ref childTasks, new CountdownEvent (1), null);
468 childTasks.AddCount ();
471 internal void ChildCompleted (AggregateException childEx)
473 if (childEx != null) {
474 if (childExceptions == null)
475 Interlocked.CompareExchange (ref childExceptions, new ConcurrentQueue<AggregateException> (), null);
476 childExceptions.Enqueue (childEx);
479 if (childTasks.Signal () && status == TaskStatus.WaitingForChildrenToComplete) {
480 status = TaskStatus.RanToCompletion;
481 ProcessChildExceptions ();
482 ProcessCompleteDelegates ();
486 internal virtual void InnerInvoke ()
488 if (action == null && simpleAction != null)
490 else if (action != null)
492 // Set action to null so that the GC can collect the delegate and thus
493 // any big object references that the user might have captured in an anonymous method
499 internal void Finish ()
501 // If there was children created and they all finished, we set the countdown
502 if (childTasks != null)
503 childTasks.Signal ();
505 // Don't override Canceled or Faulted
506 if (status == TaskStatus.Running) {
507 if (childTasks == null || childTasks.IsSet)
508 status = TaskStatus.RanToCompletion;
510 status = TaskStatus.WaitingForChildrenToComplete;
513 if (status != TaskStatus.WaitingForChildrenToComplete)
514 ProcessCompleteDelegates ();
516 // Reset the current thingies
518 TaskScheduler.Current = null;
520 if (cancellationRegistration.HasValue)
521 cancellationRegistration.Value.Dispose ();
523 // Tell parent that we are finished
524 if (CheckTaskOptions (taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null) {
525 parent.ChildCompleted (this.Exception);
529 void CompletionExecutor (Task cont)
531 if (cont.Slot.Predicate != null && !cont.Slot.Predicate ())
534 if (!cont.Slot.Launched.TryRelaxedSet ())
537 if (!ContinuationStatusCheck (cont.Slot.Kind)) {
544 if ((cont.Slot.Kind & TaskContinuationOptions.ExecuteSynchronously) != 0)
545 cont.RunSynchronously (cont.scheduler);
550 void ProcessCompleteDelegates ()
552 if (completed.HasElements) {
554 while (completed.TryGetNextCompletion (out continuation))
555 CompletionExecutor (continuation);
557 if (registeredEvts.HasElements) {
558 ManualResetEventSlim evt;
559 while (registeredEvts.TryGetNextCompletion (out evt))
564 void ProcessChildExceptions ()
566 if (childExceptions == null)
569 if (exception == null)
570 exception = new AggregateException ();
572 AggregateException childEx;
573 while (childExceptions.TryDequeue (out childEx))
574 exception.AddChildException (childEx);
578 #region Cancel and Wait related method
580 internal void CancelReal ()
582 status = TaskStatus.Canceled;
583 ProcessCompleteDelegates ();
586 internal void HandleGenericException (Exception e)
588 HandleGenericException (new AggregateException (e));
591 internal void HandleGenericException (AggregateException e)
594 Thread.MemoryBarrier ();
595 status = TaskStatus.Faulted;
596 if (scheduler != null && scheduler.FireUnobservedEvent (exception).Observed)
597 exceptionObserved = true;
602 Wait (Timeout.Infinite, CancellationToken.None);
605 public void Wait (CancellationToken cancellationToken)
607 Wait (Timeout.Infinite, cancellationToken);
610 public bool Wait (TimeSpan timeout)
612 return Wait (CheckTimeout (timeout), CancellationToken.None);
615 public bool Wait (int millisecondsTimeout)
617 return Wait (millisecondsTimeout, CancellationToken.None);
620 public bool Wait (int millisecondsTimeout, CancellationToken cancellationToken)
622 if (millisecondsTimeout < -1)
623 throw new ArgumentOutOfRangeException ("millisecondsTimeout");
628 // If the task is ready to be run and we were supposed to wait on it indefinitely, just run it
629 if (Status == TaskStatus.WaitingToRun && millisecondsTimeout == -1 && scheduler != null)
633 // Free heavy ressources used by the event automatically but without removing
634 // it from the queue since Set () doesn't trigger ObjectDisposedException
635 using (var evt = new ManualResetEventSlim ()) {
636 RegisterWaitEvent (evt);
637 result = evt.Wait (millisecondsTimeout, cancellationToken);
643 throw new AggregateException (new TaskCanceledException (this));
645 if (exception != null)
651 public static void WaitAll (params Task[] tasks)
653 WaitAll (tasks, Timeout.Infinite, CancellationToken.None);
656 public static void WaitAll (Task[] tasks, CancellationToken cancellationToken)
658 WaitAll (tasks, Timeout.Infinite, cancellationToken);
661 public static bool WaitAll (Task[] tasks, TimeSpan timeout)
663 return WaitAll (tasks, CheckTimeout (timeout), CancellationToken.None);
666 public static bool WaitAll (Task[] tasks, int millisecondsTimeout)
668 return WaitAll (tasks, millisecondsTimeout, CancellationToken.None);
671 public static bool WaitAll (Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
674 throw new ArgumentNullException ("tasks");
675 CheckForNullTasks (tasks);
678 List<Exception> exceptions = null;
679 long start = watch.ElapsedMilliseconds;
681 foreach (var t in tasks) {
683 result &= t.Wait (millisecondsTimeout, cancellationToken);
684 } catch (AggregateException e) {
685 if (exceptions == null)
686 exceptions = new List<Exception> ();
688 exceptions.AddRange (e.InnerExceptions);
690 if (!ComputeTimeout (ref millisecondsTimeout, start, watch))
696 if (exceptions != null)
697 throw new AggregateException (exceptions);
702 public static int WaitAny (params Task[] tasks)
704 return WaitAny (tasks, Timeout.Infinite, CancellationToken.None);
707 public static int WaitAny (Task[] tasks, TimeSpan timeout)
709 return WaitAny (tasks, CheckTimeout (timeout));
712 public static int WaitAny (Task[] tasks, int millisecondsTimeout)
714 return WaitAny (tasks, millisecondsTimeout, CancellationToken.None);
717 public static int WaitAny (Task[] tasks, CancellationToken cancellationToken)
719 return WaitAny (tasks, Timeout.Infinite, cancellationToken);
722 public static int WaitAny (Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
725 throw new ArgumentNullException ("tasks");
726 if (millisecondsTimeout < -1)
727 throw new ArgumentOutOfRangeException ("millisecondsTimeout");
728 CheckForNullTasks (tasks);
730 if (tasks.Length > 0) {
731 using (var evt = new ManualResetEventSlim ()) {
732 for (int i = 0; i < tasks.Length; i++) {
736 t.RegisterWaitEvent (evt);
739 if (!evt.Wait (millisecondsTimeout, cancellationToken))
744 int firstFinished = -1;
745 for (int i = 0; i < tasks.Length; i++) {
753 return firstFinished;
756 static int CheckTimeout (TimeSpan timeout)
759 return checked ((int)timeout.TotalMilliseconds);
760 } catch (System.OverflowException) {
761 throw new ArgumentOutOfRangeException ("timeout");
765 static bool ComputeTimeout (ref int millisecondsTimeout, long start, Watch watch)
767 if (millisecondsTimeout == -1)
770 return (millisecondsTimeout = millisecondsTimeout - (int)(watch.ElapsedMilliseconds - start)) >= 1;
773 static void CheckForNullTasks (Task[] tasks)
775 foreach (var t in tasks)
777 throw new ArgumentNullException ("tasks", "the tasks argument contains a null element");
782 public void Dispose ()
787 protected virtual void Dispose (bool disposing)
790 throw new InvalidOperationException ("A task may only be disposed if it is in a completion state");
792 // Set action to null so that the GC can collect the delegate and thus
793 // any big object references that the user might have captured in a anonymous method
797 if (cancellationRegistration != null)
798 cancellationRegistration.Value.Dispose ();
805 public ConfiguredTaskAwaitable ConfigureAwait (bool continueOnCapturedContext)
807 return new ConfiguredTaskAwaitable (this, continueOnCapturedContext);
810 public Task ContinueWith (Action<Task, object> continuationAction, object state)
812 return ContinueWith (continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
815 public Task ContinueWith (Action<Task, object> continuationAction, object state, CancellationToken cancellationToken)
817 return ContinueWith (continuationAction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
820 public Task ContinueWith (Action<Task, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
822 return ContinueWith (continuationAction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
825 public Task ContinueWith (Action<Task, object> continuationAction, object state, TaskScheduler scheduler)
827 return ContinueWith (continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
830 public Task ContinueWith (Action<Task, object> continuationAction, object state, CancellationToken cancellationToken,
831 TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
833 if (continuationAction == null)
834 throw new ArgumentNullException ("continuationAction");
835 if (scheduler == null)
836 throw new ArgumentNullException ("scheduler");
838 Task continuation = new Task (l => continuationAction (this, l), state,
840 GetCreationOptions (continuationOptions),
842 ContinueWithCore (continuation, continuationOptions, scheduler);
847 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state)
849 return ContinueWith<TResult> (continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
852 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
854 return ContinueWith<TResult> (continuationFunction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
857 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken)
859 return ContinueWith<TResult> (continuationFunction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
862 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler)
864 return ContinueWith<TResult> (continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
867 public Task<TResult> ContinueWith<TResult> (Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken,
868 TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
870 if (continuationFunction == null)
871 throw new ArgumentNullException ("continuationFunction");
872 if (scheduler == null)
873 throw new ArgumentNullException ("scheduler");
875 var t = new Task<TResult> (l => continuationFunction (this, l),
878 GetCreationOptions (continuationOptions),
881 ContinueWithCore (t, continuationOptions, scheduler);
886 public static Task<TResult> FromResult<TResult> (TResult result)
888 var tcs = new TaskCompletionSource<TResult> ();
889 tcs.SetResult (result);
893 public TaskAwaiter GetAwaiter ()
895 return new TaskAwaiter (this);
898 public static Task Run (Action action)
900 return Run (action, CancellationToken.None);
903 public static Task Run (Action action, CancellationToken cancellationToken)
905 if (cancellationToken.IsCancellationRequested)
906 return TaskConstants.Canceled;
908 var t = new Task (action, cancellationToken, TaskCreationOptions.DenyChildAttach);
913 public static Task Run (Func<Task> function)
915 return Run (function, CancellationToken.None);
918 public static Task Run (Func<Task> function, CancellationToken cancellationToken)
920 if (cancellationToken.IsCancellationRequested)
921 return TaskConstants.Canceled;
923 var t = new Task<Task> (function, cancellationToken);
928 public static Task<TResult> Run<TResult> (Func<TResult> function)
930 return Run (function, CancellationToken.None);
933 public static Task<TResult> Run<TResult> (Func<TResult> function, CancellationToken cancellationToken)
935 if (cancellationToken.IsCancellationRequested)
936 return TaskConstants<TResult>.Canceled;
938 var t = new Task<TResult> (function, cancellationToken, TaskCreationOptions.DenyChildAttach);
943 public static Task<TResult> Run<TResult> (Func<Task<TResult>> function)
945 return Run (function, CancellationToken.None);
948 public static Task<TResult> Run<TResult> (Func<Task<TResult>> function, CancellationToken cancellationToken)
950 if (cancellationToken.IsCancellationRequested)
951 return TaskConstants<TResult>.Canceled;
953 var t = Task<Task<TResult>>.Factory.StartNew (function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
954 return GetTaskResult (t);
957 async static Task<TResult> GetTaskResult<TResult> (Task<Task<TResult>> task)
959 var r = await task.ConfigureAwait (false);
963 public static YieldAwaitable Yield ()
965 return new YieldAwaitable ();
970 public static TaskFactory Factory {
972 return defaultFactory;
976 public static int? CurrentId {
979 return t == null ? (int?)null : t.Id;
983 public AggregateException Exception {
985 exceptionObserved = true;
994 public bool IsCanceled {
996 return status == TaskStatus.Canceled;
1000 public bool IsCompleted {
1002 return status >= TaskStatus.RanToCompletion;
1006 public bool IsFaulted {
1008 return status == TaskStatus.Faulted;
1012 public TaskCreationOptions CreationOptions {
1014 return taskCreationOptions;
1018 public TaskStatus Status {
1027 public object AsyncState {
1033 bool IAsyncResult.CompletedSynchronously {
1039 WaitHandle IAsyncResult.AsyncWaitHandle {
1051 internal Task Parent {
1057 internal string DisplayActionMethod {
1059 Delegate d = simpleAction ?? (Delegate) action;
1060 return d == null ? "<none>" : d.Method.ToString ();