Merge pull request #297 from ermshiperete/4959
[mono.git] / mcs / class / corlib / System.Threading.Tasks / TaskFactory.cs
index 62b66ca66644a7750c425812fd83119a0bfa9d90..5f3dafab164a0dcdd1281799ca8f65659e838259 100644 (file)
@@ -240,28 +240,9 @@ namespace System.Threading.Tasks
 
                public Task ContinueWhenAny (Task[] tasks, Action<Task> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
                {
-                       if (tasks == null)
-                               throw new ArgumentNullException ("tasks");
-
-                       if (tasks.Length == 0)
-                               throw new ArgumentException ("The tasks argument contains no tasks", "tasks");
+                       CheckContinueArguments (tasks, continuationAction, continuationOptions, scheduler);
 
-                       foreach (var ta in tasks) {
-                               if (ta == null)
-                                       throw new ArgumentException ("The tasks argument constains a null value", "tasks");
-                       }
-
-                       if (continuationAction == null)
-                               throw new ArgumentNullException ("continuationAction");
-
-                       var t = new Task<int> (l => {
-                               var data = (Tuple<Task[], CancellationToken>) l;
-                               return Task.WaitAny (data.Item1, data.Item2);
-                       }, Tuple.Create (tasks, cancellationToken));
-
-                       var cont = t.ContinueWith (TaskActionInvoker.Create (continuationAction, tasks), cancellationToken, continuationOptions, scheduler);
-
-                       t.Start (scheduler);
+                       var cont = Task.WhenAnyCore (tasks).ContinueWith (TaskActionInvoker.CreateSelected (continuationAction), cancellationToken, continuationOptions, scheduler);
 
                        return cont;
                }
@@ -322,14 +303,9 @@ namespace System.Threading.Tasks
                                                               TaskContinuationOptions continuationOptions,
                                                               TaskScheduler scheduler)
                {
-                       var t = new Task<int> (l => {
-                               var data = (Tuple<Task[], CancellationToken>) l;
-                               return Task.WaitAny (data.Item1, data.Item2);
-                       }, Tuple.Create (tasks, cancellationToken));
+                       CheckContinueArguments (tasks, continuationFunction, continuationOptions, scheduler);
 
-                       var cont = t.ContinueWith<TResult> (TaskActionInvoker.Create (continuationFunction, tasks), cancellationToken, continuationOptions, scheduler);
-
-                       t.Start (scheduler);
+                       var cont = Task.WhenAnyCore (tasks).ContinueWith<TResult> (TaskActionInvoker.Create (continuationFunction, tasks), cancellationToken, continuationOptions, scheduler);
 
                        return cont;
                }
@@ -386,14 +362,9 @@ namespace System.Threading.Tasks
                public Task ContinueWhenAll (Task[] tasks, Action<Task[]> continuationAction, CancellationToken cancellationToken,
                                             TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
                {
-                       var t = new Task (l => {
-                               var data = (Tuple<Task[], CancellationToken>) l;
-                               Task.WaitAll (data.Item1, data.Item2);
-                       }, Tuple.Create (tasks, cancellationToken));
+                       CheckContinueArguments (tasks, continuationAction, continuationOptions, scheduler);
 
-                       var cont = t.ContinueWith (TaskActionInvoker.Create (continuationAction, tasks), cancellationToken, continuationOptions, scheduler);
-
-                       t.Start (scheduler);
+                       var cont = Task.WhenAllCore (tasks).ContinueWith (TaskActionInvoker.Create (continuationAction, tasks), cancellationToken, continuationOptions, scheduler);
 
                        return cont;
                }
@@ -446,14 +417,9 @@ namespace System.Threading.Tasks
                                                               CancellationToken cancellationToken,
                                                               TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
                {
-                       var t = new Task (l => {
-                               var data = (Tuple<Task[], CancellationToken>) l;
-                               Task.WaitAll (data.Item1, data.Item2);
-                       }, Tuple.Create (tasks, cancellationToken));
+                       CheckContinueArguments (tasks, continuationFunction, continuationOptions, scheduler);
 
-                       var cont = t.ContinueWith<TResult> (TaskActionInvoker.Create (continuationFunction, tasks), cancellationToken, continuationOptions, scheduler);
-
-                       t.Start (scheduler);
+                       var cont = Task.WhenAllCore (tasks).ContinueWith<TResult> (TaskActionInvoker.Create (continuationFunction, tasks), cancellationToken, continuationOptions, scheduler);
 
                        return cont;
                }
@@ -656,6 +622,36 @@ namespace System.Threading.Tasks
                {
                        return scheduler ?? TaskScheduler.Current;
                }
+
+               static void CheckContinueArguments (Task[] tasks, object continuationAction, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+               {
+                       if (tasks == null)
+                               throw new ArgumentNullException ("tasks");
+
+                       if (tasks.Length == 0)
+                               throw new ArgumentException ("The tasks argument contains no tasks", "tasks");
+
+                       foreach (var ta in tasks) {
+                               if (ta == null)
+                                       throw new ArgumentException ("The tasks argument contains a null value", "tasks");
+                       }
+
+                       if (continuationAction == null)
+                               throw new ArgumentNullException ("continuationAction");
+                       if (scheduler == null)
+                               throw new ArgumentNullException ("scheduler");
+
+                       const TaskContinuationOptions notAllowedOptions = 
+                               TaskContinuationOptions.NotOnRanToCompletion  |
+                               TaskContinuationOptions.NotOnFaulted |
+                               TaskContinuationOptions.NotOnCanceled |
+                               TaskContinuationOptions.OnlyOnRanToCompletion |
+                               TaskContinuationOptions.OnlyOnFaulted |
+                               TaskContinuationOptions.OnlyOnCanceled;
+
+                       if ((continuationOptions & notAllowedOptions) != 0)
+                               throw new ArgumentOutOfRangeException ("continuationOptions");
+               }
        }
 }
 #endif