Statistics
| Branch: | Revision:

root / trunk / Pithos.Core / TaskExtensions.cs @ cfed7823

History | View | Annotate | Download (4.5 kB)

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
}