2 using System.Collections.Generic;
3 using System.Diagnostics.Contracts;
6 using System.Threading;
7 using System.Threading.Tasks;
11 static class TaskExtensions
13 public static Task<T2> Then<T1, T2>(this Task<T1> first, Func<T1, Task<T2>> next)
16 throw new ArgumentNullException("first");
18 throw new ArgumentNullException("next");
19 Contract.EndContractBlock();
20 return Then(first, next, CancellationToken.None);
23 public static Task Then<T1>(this Task<T1> first, Func<T1, Task> next)
26 throw new ArgumentNullException("first");
28 throw new ArgumentNullException("next");
29 Contract.EndContractBlock();
30 return Then(first, next, CancellationToken.None);
33 public static Task<T2> Then<T1, T2>(this Task<T1> first, Func<T1, Task<T2>> next, CancellationToken cancellationToken)
36 throw new ArgumentNullException("first");
38 throw new ArgumentNullException("next");
39 Contract.EndContractBlock();
40 Contract.Assume(TaskScheduler.Current!=null);
42 var tcs = new TaskCompletionSource<T2>();
43 first.ContinueWith(delegate
45 if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions);
46 else if (first.IsCanceled) tcs.TrySetCanceled();
51 var t = next(first.Result);
52 if (t == null) tcs.TrySetCanceled();
53 else t.ContinueWith(delegate
55 if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions);
56 else if (t.IsCanceled) tcs.TrySetCanceled();
57 else tcs.TrySetResult(t.Result);
58 }, TaskContinuationOptions.ExecuteSynchronously);
60 catch (Exception exc) { tcs.TrySetException(exc); }
62 }, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Current);
66 public static Task Then<T1>(this Task<T1> first, Func<T1, Task> next, CancellationToken cancellationToken)
69 throw new ArgumentNullException("first");
71 throw new ArgumentNullException("next");
72 Contract.EndContractBlock();
73 Contract.Assume(TaskScheduler.Current != null);
75 var tcs = new TaskCompletionSource<object>();
76 first.ContinueWith(delegate
78 if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions);
79 else if (first.IsCanceled) tcs.TrySetCanceled();
84 var t = next(first.Result);
85 if (t == null) tcs.TrySetCanceled();
86 else t.ContinueWith(delegate
88 if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions);
89 else if (t.IsCanceled) tcs.TrySetCanceled();
90 else tcs.TrySetResult(null);
91 }, TaskContinuationOptions.ExecuteSynchronously);
93 catch (Exception exc) { tcs.TrySetException(exc); }
95 }, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Current);
101 public static void ReportExceptions(this Task task,Action<AggregateException> OnError,Action OnSuccess )
103 if (!task.IsCompleted) throw new InvalidOperationException("The task has not completed.");
105 task.Exception.Handle(exc=>
107 OnError(task.Exception);