Merge pull request #799 from kebby/master
[mono.git] / mcs / class / corlib / System.Threading.Tasks / Task.cs
index 5133e20351d14bafb5dad9755472cee980f7d942..5eefcb7da5f87592bc67d2751e579f0b95ed1055 100644 (file)
@@ -49,8 +49,8 @@ namespace System.Threading.Tasks
                
                // parent is the outer task in which this task is created
                readonly Task parent;
-               // contAncestor is the Task on which this continuation was setup
-               readonly Task contAncestor;
+               // A reference to a Task on which this continuation is attached to
+               Task contAncestor;
                
                static int          id = -1;
                static readonly TaskFactory defaultFactory = new TaskFactory ();
@@ -214,7 +214,6 @@ namespace System.Threading.Tasks
                internal void RunSynchronouslyCore (TaskScheduler scheduler)
                {
                        SetupScheduler (scheduler);
-                       var saveStatus = status;
                        Status = TaskStatus.WaitingToRun;
 
                        try {
@@ -224,8 +223,7 @@ namespace System.Threading.Tasks
                                throw new TaskSchedulerException (inner);
                        }
 
-                       Status = saveStatus;
-                       Start (scheduler);
+                       Schedule ();
                        Wait ();
                }
                #endregion
@@ -502,7 +500,9 @@ namespace System.Threading.Tasks
                void InnerInvoke ()
                {
                        if (IsContinuation) {
-                               invoker.Invoke (contAncestor, state, this);
+                               var ancestor = contAncestor;
+                               contAncestor = null;
+                               invoker.Invoke (ancestor, state, this);
                        } else {
                                invoker.Invoke (this, state, this);
                        }
@@ -959,11 +959,23 @@ namespace System.Threading.Tasks
                        if (millisecondsDelay < -1)
                                throw new ArgumentOutOfRangeException ("millisecondsDelay");
 
-                       var task = new Task (TaskActionInvoker.Delay, millisecondsDelay, cancellationToken, TaskCreationOptions.None, null, TaskConstants.Finished);
-                       task.SetupScheduler (TaskScheduler.Current);
-                       
-                       if (millisecondsDelay != Timeout.Infinite)
-                               task.scheduler.QueueTask (task);
+                       if (cancellationToken.IsCancellationRequested)
+                               return TaskConstants.Canceled;
+
+                       var task = new Task (TaskActionInvoker.Empty, null, cancellationToken, TaskCreationOptions.None, null, null);
+                       task.SetupScheduler (TaskScheduler.Default);
+
+                       if (millisecondsDelay != Timeout.Infinite) {
+                               var timer = new Timer (delegate (object state) {
+                                       var t = (Task) state;
+                                       if (t.Status == TaskStatus.WaitingForActivation) {
+                                               t.Status = TaskStatus.Running;
+                                               t.Finish ();
+                                       }
+                               }, task, millisecondsDelay, -1);
+
+                               task.ContinueWith (new DisposeContinuation (timer));
+                       }
 
                        return task;
                }
@@ -1070,6 +1082,9 @@ namespace System.Threading.Tasks
 
                internal static Task<TResult[]> WhenAllCore<TResult> (IList<Task<TResult>> tasks)
                {
+                       if (tasks.Count == 0)
+                               return FromResult(new TResult[0]);
+
                        foreach (var t in tasks) {
                                if (t == null)
                                        throw new ArgumentException ("tasks", "the tasks argument contains a null element");