Add unit test for AggregateException.GetBaseException that works on .net but is broke...
[mono.git] / mcs / class / corlib / System.Threading.Tasks / TaskFactory.cs
1 // 
2 // TaskFactory.cs
3 //  
4 // Authors:
5 //       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
6 //       Marek Safar <marek.safar@gmail.com>
7 // 
8 // Copyright (c) 2009 Jérémie "Garuma" Laval
9 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
10 // 
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:
17 // 
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 // 
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
27 // THE SOFTWARE.
28
29 #if NET_4_0
30
31 namespace System.Threading.Tasks
32 {
33         public class TaskFactory
34         {
35                 readonly TaskScheduler scheduler;
36                 TaskCreationOptions creationOptions;
37                 TaskContinuationOptions continuationOptions;
38                 CancellationToken cancellationToken;
39                 
40                 public TaskFactory ()
41                         : this (CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, null)
42                 {
43                 }
44
45                 public TaskFactory (CancellationToken cancellationToken)
46                         : this (cancellationToken, TaskCreationOptions.None, TaskContinuationOptions.None, null)
47                 {       
48                 }
49
50                 public TaskFactory (TaskScheduler scheduler)
51                         : this (CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
52                 {       
53                 }
54                 
55                 public TaskFactory (TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions)
56                         : this (CancellationToken.None, creationOptions, continuationOptions, null)
57                 {       
58                 }
59                 
60                 public TaskFactory (CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions,
61                                     TaskScheduler scheduler)
62                 {
63                         this.cancellationToken = cancellationToken;
64                         this.scheduler = scheduler;
65                         this.creationOptions = creationOptions;
66                         this.continuationOptions = continuationOptions;
67
68                         CheckContinuationOptions (continuationOptions);
69                 }
70                 
71                 public TaskScheduler Scheduler {
72                         get {
73                                 return scheduler;
74                         }
75                 }
76                 
77                 public TaskContinuationOptions ContinuationOptions {
78                         get {
79                                 return continuationOptions;
80                         }
81                 }
82                 
83                 public TaskCreationOptions CreationOptions {
84                         get {
85                                 return creationOptions;
86                         }
87                 }
88                 
89                 public CancellationToken CancellationToken {
90                         get {
91                                 return cancellationToken;
92                         }
93                 }
94
95                 internal static void CheckContinuationOptions (TaskContinuationOptions continuationOptions)
96                 {
97                         if ((continuationOptions & (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion)) != 0)
98                                 throw new ArgumentOutOfRangeException ("continuationOptions");
99
100                         const TaskContinuationOptions long_running = TaskContinuationOptions.LongRunning | TaskContinuationOptions.ExecuteSynchronously;
101                         if ((continuationOptions & long_running) == long_running)
102                                 throw new ArgumentOutOfRangeException ("continuationOptions", "Synchronous continuations cannot be long running");
103                 }
104                 
105                 #region StartNew for Task
106                 public Task StartNew (Action action)
107                 {
108                         return StartNew (action, cancellationToken, creationOptions, GetScheduler ());
109                 }
110                 
111                 public Task StartNew (Action action, CancellationToken cancellationToken)
112                 {
113                         return StartNew (action, cancellationToken, creationOptions, GetScheduler ());
114                 }
115                 
116                 public Task StartNew (Action action, TaskCreationOptions creationOptions)
117                 {
118                         return StartNew (action, cancellationToken, creationOptions, GetScheduler ());
119                 }
120
121                 public Task StartNew (Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
122                 {
123                         Task t = new Task (action, cancellationToken, creationOptions);
124
125                         //
126                         // Don't start cancelled task it would throw an exception
127                         //
128                         if (!t.IsCompleted)
129                                 t.Start (scheduler);
130
131                         return t;
132                 }
133                 
134                 public Task StartNew (Action<object> action, object state)
135                 {
136                         return StartNew (action, state, cancellationToken, creationOptions, GetScheduler ());
137                 }
138                 
139                 public Task StartNew (Action<object> action, object state, CancellationToken cancellationToken)
140                 {
141                         return StartNew (action, state, cancellationToken, creationOptions, GetScheduler ());
142                 }
143                 
144                 public Task StartNew (Action<object> action, object state, TaskCreationOptions creationOptions)
145                 {
146                         return StartNew (action, state, cancellationToken, creationOptions, GetScheduler ());
147                 }
148                 
149                 public Task StartNew (Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions,
150                                       TaskScheduler scheduler)
151                 {
152                         Task t = new Task (action, state, cancellationToken, creationOptions);
153
154                         //
155                         // Don't start cancelled task it would throw an exception
156                         //
157                         if (!t.IsCompleted)
158                                 t.Start (scheduler);
159                         
160                         return t;
161                 }
162                 #endregion
163                 
164                 #region StartNew for Task<TResult>      
165                 public Task<TResult> StartNew<TResult> (Func<TResult> function)
166                 {
167                         return StartNew<TResult> (function, cancellationToken, creationOptions, GetScheduler ());
168                 }
169                 
170                 public Task<TResult> StartNew<TResult> (Func<TResult> function, TaskCreationOptions creationOptions)
171                 {
172                         return StartNew<TResult> (function, cancellationToken, creationOptions, GetScheduler ());
173
174                 }
175                 
176                 public Task<TResult> StartNew<TResult> (Func<TResult> function, CancellationToken cancellationToken)
177                 {
178                         return StartNew<TResult> (function, cancellationToken, creationOptions, GetScheduler ());
179                 }
180                 
181                 public Task<TResult> StartNew<TResult> (Func<TResult> function,
182                                                         CancellationToken cancellationToken,
183                                                         TaskCreationOptions creationOptions,
184                                                         TaskScheduler scheduler)
185                 {
186                         var t = new Task<TResult> (function, cancellationToken, creationOptions);
187
188                         //
189                         // Don't start cancelled task it would throw an exception
190                         //
191                         if (!t.IsCompleted)
192                                 t.Start (scheduler);
193
194                         return t;
195                 }
196                 
197                 public Task<TResult> StartNew<TResult> (Func<object, TResult> function, object state)
198                 {
199                         return StartNew<TResult> (function, state, cancellationToken, creationOptions, GetScheduler ());
200                 }
201                 
202                 public Task<TResult> StartNew<TResult> (Func<object, TResult> function, object state, CancellationToken cancellationToken)
203                 {
204                         return StartNew<TResult> (function, state, cancellationToken, creationOptions, GetScheduler ());
205                 }
206                 
207                 public Task<TResult> StartNew<TResult> (Func<object, TResult> function, object state, TaskCreationOptions creationOptions)
208                 {
209                         return StartNew<TResult> (function, state, cancellationToken, creationOptions, GetScheduler ());
210                 }
211                 
212                 public Task<TResult> StartNew<TResult> (Func<object, TResult> function, object state,
213                                                         CancellationToken cancellationToken,
214                                                         TaskCreationOptions creationOptions,
215                                                         TaskScheduler scheduler)
216                 {
217                         Task<TResult> t = new Task<TResult> (function, state, cancellationToken, creationOptions);
218                         t.Start (scheduler);
219                         
220                         return t;
221                 }
222                 #endregion
223                 
224                 #region Continue
225                 
226                 public Task ContinueWhenAny (Task[] tasks, Action<Task> continuationAction)
227                 {
228                         return ContinueWhenAny (tasks, continuationAction, cancellationToken, continuationOptions, GetScheduler ());
229                 }
230                 
231                 public Task ContinueWhenAny (Task[] tasks, Action<Task> continuationAction, CancellationToken cancellationToken)
232                 {
233                         return ContinueWhenAny (tasks, continuationAction, cancellationToken, continuationOptions, GetScheduler ());
234                 }
235                 
236                 public Task ContinueWhenAny (Task[] tasks, Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
237                 {
238                         return ContinueWhenAny (tasks, continuationAction, cancellationToken, continuationOptions, GetScheduler ());
239                 }
240
241                 public Task ContinueWhenAny (Task[] tasks, Action<Task> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
242                 {
243                         CheckContinueArguments (tasks, continuationAction, continuationOptions, scheduler);
244
245                         var cont = Task.WhenAnyCore (tasks).ContinueWith (TaskActionInvoker.CreateSelected (continuationAction), cancellationToken, continuationOptions, scheduler);
246
247                         return cont;
248                 }
249                 
250                 public Task ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
251                                                                 Action<Task<TAntecedentResult>> continuationAction)
252                 {
253                         return ContinueWhenAny (tasks, continuationAction, cancellationToken, continuationOptions, GetScheduler ());
254                 }
255                 
256                 public Task ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
257                                                                 Action<Task<TAntecedentResult>> continuationAction,
258                                                                 CancellationToken cancellationToken)
259                 {
260                         return ContinueWhenAny (tasks, continuationAction, cancellationToken, continuationOptions, GetScheduler ());
261                 }
262                 
263                 public Task ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
264                                                                 Action<Task<TAntecedentResult>> continuationAction,
265                                                                 TaskContinuationOptions continuationOptions)
266                 {
267                         return ContinueWhenAny (tasks, continuationAction, cancellationToken, continuationOptions, GetScheduler ());
268                 }
269
270                 public Task ContinueWhenAny<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
271                                                                 Action<Task<TAntecedentResult>> continuationAction,
272                                                                 CancellationToken cancellationToken,
273                                                                 TaskContinuationOptions continuationOptions,
274                                                                 TaskScheduler scheduler)
275                 {
276                         return ContinueWhenAny ((Task[]) tasks,
277                                                 (o) => continuationAction ((Task<TAntecedentResult>)o),
278                                                 cancellationToken, continuationOptions, scheduler);
279                 }
280
281                 public Task<TResult> ContinueWhenAny<TResult> (Task[] tasks, Func<Task, TResult> continuationFunction)
282                 {
283                         return ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
284                 }
285
286                 public Task<TResult> ContinueWhenAny<TResult> (Task[] tasks,
287                                                                Func<Task, TResult> continuationFunction,
288                                                                CancellationToken cancellationToken)
289                 {
290                         return ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
291                 }
292
293                 public Task<TResult> ContinueWhenAny<TResult> (Task[] tasks,
294                                                                Func<Task, TResult> continuationFunction,
295                                                                TaskContinuationOptions continuationOptions)
296                 {
297                         return ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
298                 }
299
300                 public Task<TResult> ContinueWhenAny<TResult> (Task[] tasks,
301                                                                Func<Task, TResult> continuationFunction,
302                                                                CancellationToken cancellationToken,
303                                                                TaskContinuationOptions continuationOptions,
304                                                                TaskScheduler scheduler)
305                 {
306                         CheckContinueArguments (tasks, continuationFunction, continuationOptions, scheduler);
307
308                         var cont = Task.WhenAnyCore (tasks).ContinueWith<TResult> (TaskActionInvoker.CreateSelected (continuationFunction), cancellationToken, continuationOptions, scheduler);
309
310                         return cont;
311                 }
312
313                 public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks,
314                                                                                   Func<Task<TAntecedentResult>, TResult> continuationFunction)
315                 {
316                         return ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
317                 }
318
319                 public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks,
320                                                                                   Func<Task<TAntecedentResult>, TResult> continuationFunction,
321                                                                                   CancellationToken cancellationToken)
322                 {
323                         return ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
324                 }
325
326                 public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks,
327                                                                                   Func<Task<TAntecedentResult>, TResult> continuationFunction,
328                                                                                   TaskContinuationOptions continuationOptions)
329                 {
330                         return ContinueWhenAny (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
331                 }
332
333                 public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks,
334                                                                                   Func<Task<TAntecedentResult>, TResult> continuationFunction,
335                                                                                   CancellationToken cancellationToken,
336                                                                                   TaskContinuationOptions continuationOptions,
337                                                                                   TaskScheduler scheduler)
338                 {
339                         return ContinueWhenAny<TResult> ((Task[])tasks,
340                                                          (t) => continuationFunction((Task<TAntecedentResult>)t),
341                                                          cancellationToken,
342                                                          continuationOptions,
343                                                          scheduler);
344                 }
345                 
346                 public Task ContinueWhenAll (Task[] tasks, Action<Task[]> continuationAction)
347                 {
348                         return ContinueWhenAll (tasks, continuationAction, cancellationToken, continuationOptions, GetScheduler ());
349                 }
350                 
351                 public Task ContinueWhenAll (Task[] tasks, Action<Task[]> continuationAction, CancellationToken cancellationToken)
352                 {
353                         return ContinueWhenAll (tasks, continuationAction, cancellationToken, continuationOptions, GetScheduler ());
354                 }
355                 
356                 public Task ContinueWhenAll (Task[] tasks, Action<Task[]> continuationAction,
357                                              TaskContinuationOptions continuationOptions)
358                 {
359                         return ContinueWhenAll (tasks, continuationAction, cancellationToken, continuationOptions, GetScheduler ());
360                 }
361                 
362                 public Task ContinueWhenAll (Task[] tasks, Action<Task[]> continuationAction, CancellationToken cancellationToken,
363                                              TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
364                 {
365                         CheckContinueArguments (tasks, continuationAction, continuationOptions, scheduler);
366
367                         var cont = Task.WhenAllCore (tasks).ContinueWith (TaskActionInvoker.Create (continuationAction, tasks), cancellationToken, continuationOptions, scheduler);
368
369                         return cont;
370                 }
371                 
372                 public Task ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
373                                                                 Action<Task<TAntecedentResult>[]> continuationAction)
374                 {
375                         return ContinueWhenAll (tasks, continuationAction, cancellationToken, continuationOptions, GetScheduler ());
376                 }
377                 
378                 public Task ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks,
379                                                                 Action<Task<TAntecedentResult>[]> continuationAction, CancellationToken cancellationToken)
380                 {
381                         return ContinueWhenAll (tasks, continuationAction, cancellationToken, continuationOptions, GetScheduler ());
382                 }
383                 
384                 public Task ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction,
385                                                                 TaskContinuationOptions continuationOptions)
386                 {
387                         return ContinueWhenAll (tasks, continuationAction, cancellationToken, continuationOptions, GetScheduler ());
388                 }
389                 
390                 public Task ContinueWhenAll<TAntecedentResult> (Task<TAntecedentResult>[] tasks, 
391                                                                 Action<Task<TAntecedentResult>[]> continuationAction,
392                                                                 CancellationToken cancellationToken, TaskContinuationOptions continuationOptions,
393                                                                 TaskScheduler scheduler)
394                 {
395                         return ContinueWhenAll ((Task[]) tasks, (o) => continuationAction (tasks), cancellationToken,
396                                                 continuationOptions, scheduler);
397                 }
398                 
399                 public Task<TResult> ContinueWhenAll<TResult> (Task[] tasks, Func<Task[], TResult> continuationFunction)
400                 {
401                         return ContinueWhenAll<TResult> (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
402                 }
403                 
404                 public Task<TResult> ContinueWhenAll<TResult> (Task[] tasks, Func<Task[], TResult> continuationFunction,
405                                                                TaskContinuationOptions continuationOptions)
406                 {
407                         return ContinueWhenAll<TResult> (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
408                 }
409                 
410                 public Task<TResult> ContinueWhenAll<TResult> (Task[] tasks, Func<Task[], TResult> continuationFunction,
411                                                                CancellationToken cancellationToken)
412                 {
413                         return ContinueWhenAll<TResult> (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
414                 }
415                 
416                 public Task<TResult> ContinueWhenAll<TResult> (Task[] tasks, Func<Task[], TResult> continuationFunction,
417                                                                CancellationToken cancellationToken,
418                                                                TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
419                 {
420                         CheckContinueArguments (tasks, continuationFunction, continuationOptions, scheduler);
421
422                         var cont = Task.WhenAllCore (tasks).ContinueWith<TResult> (TaskActionInvoker.Create (continuationFunction, tasks), cancellationToken, continuationOptions, scheduler);
423
424                         return cont;
425                 }
426                 
427                 public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks,
428                                                                                   Func<Task<TAntecedentResult>[], TResult> continuationFunction)
429                 {
430                         return ContinueWhenAll<TAntecedentResult, TResult> (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
431                 }
432                 
433                 public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks, 
434                                                                                   Func<Task<TAntecedentResult>[], TResult> continuationFunction,
435                                                                                   TaskContinuationOptions continuationOptions)
436                 {
437                         return ContinueWhenAll<TAntecedentResult, TResult> (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
438                 }
439                 
440                 public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks,
441                                                                                   Func<Task<TAntecedentResult>[], TResult> continuationFunction,
442                                                                                   CancellationToken cancellationToken)
443                 {
444                         return ContinueWhenAll<TAntecedentResult, TResult> (tasks, continuationFunction, cancellationToken, continuationOptions, GetScheduler ());
445                 }
446                 
447                 public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult> (Task<TAntecedentResult>[] tasks, 
448                                                                                   Func<Task<TAntecedentResult>[], TResult> continuationFunction,
449                                                                                   CancellationToken cancellationToken,
450                                                                                   TaskContinuationOptions continuationOptions,
451                                                                                   TaskScheduler scheduler)
452                 {
453                         return ContinueWhenAll<TResult> ((Task[]) tasks,
454                                                          (o) => continuationFunction (tasks),
455                                                          cancellationToken,
456                                                          continuationOptions, scheduler);
457                 }
458
459                 #endregion
460
461                 #region FromAsync IAsyncResult
462                 
463                 public Task FromAsync (IAsyncResult asyncResult, Action<IAsyncResult> endMethod)
464                 {
465                         return FromAsync (asyncResult, endMethod, creationOptions);
466                 }
467                 
468                 public Task FromAsync (IAsyncResult asyncResult, Action<IAsyncResult> endMethod, TaskCreationOptions creationOptions)
469                 {
470                         return FromAsync (asyncResult, endMethod, creationOptions, GetScheduler ());
471                 }
472
473                 public Task FromAsync (IAsyncResult asyncResult, Action<IAsyncResult> endMethod, TaskCreationOptions creationOptions, TaskScheduler scheduler)
474                 {
475                         if (endMethod == null)
476                                 throw new ArgumentNullException ("endMethod");
477
478                         return TaskFactory<object>.FromIAsyncResult (asyncResult,
479                                 l => {
480                                         endMethod (asyncResult);
481                                         return null;
482                                 }, creationOptions, scheduler);
483                 }
484                 
485                 public Task<TResult> FromAsync<TResult> (IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod)
486                 {
487                         return FromAsync<TResult> (asyncResult, endMethod, creationOptions);
488                 }
489                 
490                 public Task<TResult> FromAsync<TResult> (IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod, TaskCreationOptions creationOptions)
491                 {
492                         return FromAsync<TResult> (asyncResult, endMethod, creationOptions, GetScheduler ());
493                 }
494                 
495                 public Task<TResult> FromAsync<TResult> (IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod, TaskCreationOptions creationOptions, TaskScheduler scheduler)
496                 {
497                         return TaskFactory<TResult>.FromIAsyncResult (asyncResult, endMethod, creationOptions, scheduler);
498                 }
499
500                 #endregion
501
502                 #region FromAsync Begin/End Method
503
504                 public Task FromAsync (Func<AsyncCallback, object, IAsyncResult> beginMethod, Action<IAsyncResult> endMethod, object state)
505                 {
506                         return FromAsync (beginMethod, endMethod, state, creationOptions);
507                 }
508
509                 public Task FromAsync (Func<AsyncCallback, object, IAsyncResult> beginMethod, Action<IAsyncResult> endMethod,
510                                                            object state, TaskCreationOptions creationOptions)
511                 {
512                         return TaskFactory<object>.FromAsyncBeginEnd (beginMethod,
513                                 l => { endMethod (l); return null; },
514                                 state, creationOptions);
515                 }
516
517                 public Task FromAsync<TArg1> (Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod, Action<IAsyncResult> endMethod,
518                                                   TArg1 arg1, object state)
519                 {
520                         return FromAsync (beginMethod, endMethod, arg1, state, creationOptions);
521                 }
522
523                 public Task FromAsync<TArg1> (Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod, Action<IAsyncResult> endMethod,
524                                               TArg1 arg1, object state, TaskCreationOptions creationOptions)
525                 {
526                         if (endMethod == null)
527                                 throw new ArgumentNullException ("endMethod");
528
529                         return TaskFactory<object>.FromAsyncBeginEnd (beginMethod,
530                                 l => { endMethod (l); return null; },
531                                 arg1, state, creationOptions);
532                 }
533
534                 public Task FromAsync<TArg1, TArg2> (Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
535                                                      Action<IAsyncResult> endMethod,
536                                                      TArg1 arg1, TArg2 arg2, object state)
537                 {
538                         return FromAsync (beginMethod, endMethod, arg1, arg2, state, creationOptions);
539                 }
540
541                 public Task FromAsync<TArg1, TArg2> (Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
542                                                      Action<IAsyncResult> endMethod,
543                                                      TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
544                 {
545                         if (endMethod == null)
546                                 throw new ArgumentNullException ("endMethod");
547
548                         return TaskFactory<object>.FromAsyncBeginEnd (beginMethod,
549                                 l => { endMethod (l); return null; },
550                                 arg1, arg2, state, creationOptions);
551                 }
552
553                 public Task FromAsync<TArg1, TArg2, TArg3> (Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod, Action<IAsyncResult> endMethod,
554                                                             TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
555                 {
556                         return FromAsync (beginMethod, endMethod, arg1, arg2, arg3, state, creationOptions);
557                 }
558
559                 public Task FromAsync<TArg1, TArg2, TArg3> (Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod, Action<IAsyncResult> endMethod,
560                                                             TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
561                 {
562                         if (endMethod == null)
563                                 throw new ArgumentNullException ("endMethod");
564
565                         return TaskFactory<object>.FromAsyncBeginEnd (beginMethod,
566                                 l => { endMethod (l); return null; },
567                                 arg1, arg2, arg3, state, creationOptions);
568                 }
569
570                 public Task<TResult> FromAsync<TResult> (Func<AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
571                                                          object state)
572                 {
573                         return FromAsync (beginMethod, endMethod, state, creationOptions);
574                 }
575
576                 public Task<TResult> FromAsync<TResult> (Func<AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
577                                                          object state, TaskCreationOptions creationOptions)
578                 {
579                         return TaskFactory<TResult>.FromAsyncBeginEnd (beginMethod, endMethod, state, creationOptions);
580                 }
581
582                 public Task<TResult> FromAsync<TArg1, TResult> (Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
583                                                                 TArg1 arg1, object state)
584                 {
585                         return FromAsync (beginMethod, endMethod, arg1, state, creationOptions);
586                 }
587
588                 public Task<TResult> FromAsync<TArg1, TResult> (Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
589                                                                 TArg1 arg1, object state, TaskCreationOptions creationOptions)
590                 {
591                         return TaskFactory<TResult>.FromAsyncBeginEnd (beginMethod, endMethod, arg1, state, creationOptions);
592                 }
593
594                 public Task<TResult> FromAsync<TArg1, TArg2, TResult> (Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
595                                                                        Func<IAsyncResult, TResult> endMethod,
596                                                                        TArg1 arg1, TArg2 arg2, object state)
597                 {
598                         return FromAsync (beginMethod, endMethod, arg1, arg2, state, creationOptions);
599                 }
600
601                 public Task<TResult> FromAsync<TArg1, TArg2, TResult> (Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
602                                                                        TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
603                 {
604                         return TaskFactory<TResult>.FromAsyncBeginEnd (beginMethod, endMethod, arg1, arg2, state, creationOptions);
605                 }
606
607                 public Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult> (Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
608                                                                               TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
609                 {
610                         return FromAsync (beginMethod, endMethod, arg1, arg2, arg3, state, creationOptions);
611                 }
612
613                 public Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult> (Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, TResult> endMethod,
614                                                                               TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
615                 {
616                         return TaskFactory<TResult>.FromAsyncBeginEnd (beginMethod, endMethod, arg1, arg2, arg3, state, creationOptions);
617                 }
618
619                 #endregion
620
621                 TaskScheduler GetScheduler ()
622                 {
623                         return scheduler ?? TaskScheduler.Current;
624                 }
625
626                 static void CheckContinueArguments (Task[] tasks, object continuationAction, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
627                 {
628                         if (tasks == null)
629                                 throw new ArgumentNullException ("tasks");
630
631                         if (tasks.Length == 0)
632                                 throw new ArgumentException ("The tasks argument contains no tasks", "tasks");
633
634                         foreach (var ta in tasks) {
635                                 if (ta == null)
636                                         throw new ArgumentException ("The tasks argument contains a null value", "tasks");
637                         }
638
639                         if (continuationAction == null)
640                                 throw new ArgumentNullException ("continuationAction");
641                         if (scheduler == null)
642                                 throw new ArgumentNullException ("scheduler");
643
644                         const TaskContinuationOptions notAllowedOptions = 
645                                 TaskContinuationOptions.NotOnRanToCompletion  |
646                                 TaskContinuationOptions.NotOnFaulted |
647                                 TaskContinuationOptions.NotOnCanceled |
648                                 TaskContinuationOptions.OnlyOnRanToCompletion |
649                                 TaskContinuationOptions.OnlyOnFaulted |
650                                 TaskContinuationOptions.OnlyOnCanceled;
651
652                         if ((continuationOptions & notAllowedOptions) != 0)
653                                 throw new ArgumentOutOfRangeException ("continuationOptions");
654                 }
655         }
656 }
657 #endif