Added log4net for client profile
[pithos-ms-client] / trunk / Pithos.Core / TaskExtensions.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics.Contracts;
4 using System.Linq;
5 using System.Text;
6 using System.Threading;
7 using System.Threading.Tasks;
8
9 namespace Pithos.Core
10 {
11     static class TaskExtensions
12     {
13         public static Task<T2> Then<T1, T2>(this Task<T1> first, Func<T1, Task<T2>> next)
14         {
15             if (first == null)
16                 throw new ArgumentNullException("first");
17             if (next == null)
18                 throw new ArgumentNullException("next");
19             Contract.EndContractBlock();
20             return Then(first, next, CancellationToken.None);
21         }
22
23         public static Task Then<T1>(this Task<T1> first, Func<T1, Task> next)
24         {
25             if (first == null)
26                 throw new ArgumentNullException("first");
27             if (next == null)
28                 throw new ArgumentNullException("next");
29             Contract.EndContractBlock();
30             return Then(first, next, CancellationToken.None);
31         }
32
33         public static Task<T2> Then<T1, T2>(this Task<T1> first, Func<T1, Task<T2>> next, CancellationToken cancellationToken)
34         {
35             if (first == null) 
36                 throw new ArgumentNullException("first");
37             if (next == null) 
38                 throw new ArgumentNullException("next");
39             Contract.EndContractBlock();
40             Contract.Assume(TaskScheduler.Current!=null);
41
42             var tcs = new TaskCompletionSource<T2>();
43             first.ContinueWith(delegate
44             {
45                 if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions);
46                 else if (first.IsCanceled) tcs.TrySetCanceled();
47                 else
48                 {
49                     try
50                     {
51                         var t = next(first.Result);
52                         if (t == null) tcs.TrySetCanceled();
53                         else t.ContinueWith(delegate
54                         {
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);
59                     }
60                     catch (Exception exc) { tcs.TrySetException(exc); }
61                 }
62             }, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Current);
63             return tcs.Task;
64         }
65
66         public static Task Then<T1>(this Task<T1> first, Func<T1, Task> next, CancellationToken cancellationToken)
67         {
68             if (first == null)
69                 throw new ArgumentNullException("first");
70             if (next == null)
71                 throw new ArgumentNullException("next");
72             Contract.EndContractBlock();
73             Contract.Assume(TaskScheduler.Current != null);
74
75             var tcs = new TaskCompletionSource<object>();
76             first.ContinueWith(delegate
77             {
78                 if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions);
79                 else if (first.IsCanceled) tcs.TrySetCanceled();
80                 else
81                 {
82                     try
83                     {
84                         var t = next(first.Result);
85                         if (t == null) tcs.TrySetCanceled();
86                         else t.ContinueWith(delegate
87                         {
88                             if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions);
89                             else if (t.IsCanceled) tcs.TrySetCanceled();
90                             else tcs.TrySetResult(null);
91                         }, TaskContinuationOptions.ExecuteSynchronously);
92                     }
93                     catch (Exception exc) { tcs.TrySetException(exc); }
94                 }
95             }, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Current);
96             return tcs.Task;
97         }
98
99
100
101         public static void ReportExceptions(this Task task,Action<AggregateException> OnError,Action OnSuccess )
102         {
103             if (!task.IsCompleted) throw new InvalidOperationException("The task has not completed.");
104             if (task.IsFaulted)             
105                 task.Exception.Handle(exc=>
106                                           {
107                                               OnError(task.Exception);
108                                               return true;
109                                           }); 
110             else
111             {
112                 OnSuccess();
113             }
114         }
115
116     }
117 }