Statistics
| Branch: | Revision:

root / trunk / Pithos.Core / TaskExtensions.cs @ 73cdd135

History | View | Annotate | Download (5.5 kB)

1
using System;
2
using System.Collections.Concurrent;
3
using System.Collections.Generic;
4
using System.Diagnostics.Contracts;
5
using System.Linq;
6
using System.Text;
7
using System.Threading;
8
using System.Threading.Tasks;
9

    
10
namespace Pithos.Core
11
{
12
    public static class TaskExtensions
13
    {
14
        public static Task<T2> Then<T1, T2>(this Task<T1> first, Func<T1, Task<T2>> next)
15
        {
16
            if (first == null)
17
                throw new ArgumentNullException("first");
18
            if (next == null)
19
                throw new ArgumentNullException("next");
20
            Contract.EndContractBlock();
21
            return Then(first, next, CancellationToken.None);
22
        }
23

    
24
        public static Task Then<T1>(this Task<T1> first, Func<T1, Task> next)
25
        {
26
            if (first == null)
27
                throw new ArgumentNullException("first");
28
            if (next == null)
29
                throw new ArgumentNullException("next");
30
            Contract.EndContractBlock();
31
            return Then(first, next, CancellationToken.None);
32
        }
33

    
34
        public static Task<T2> Then<T1, T2>(this Task<T1> first, Func<T1, Task<T2>> next, CancellationToken cancellationToken)
35
        {
36
            if (first == null) 
37
                throw new ArgumentNullException("first");
38
            if (next == null) 
39
                throw new ArgumentNullException("next");
40
            Contract.EndContractBlock();
41
            Contract.Assume(TaskScheduler.Current!=null);
42

    
43
            var tcs = new TaskCompletionSource<T2>();
44
            first.ContinueWith(delegate
45
            {
46
                if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions);
47
                else if (first.IsCanceled) tcs.TrySetCanceled();
48
                else
49
                {
50
                    try
51
                    {
52
                        var t = next(first.Result);
53
                        if (t == null) tcs.TrySetCanceled();
54
                        else t.ContinueWith(delegate
55
                        {
56
                            if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions);
57
                            else if (t.IsCanceled) tcs.TrySetCanceled();
58
                            else tcs.TrySetResult(t.Result);
59
                        }, TaskContinuationOptions.ExecuteSynchronously);
60
                    }
61
                    catch (Exception exc) { tcs.TrySetException(exc); }
62
                }
63
            }, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Current);
64
            return tcs.Task;
65
        }
66

    
67
        public static Task Then<T1>(this Task<T1> first, Func<T1, Task> next, CancellationToken cancellationToken)
68
        {
69
            if (first == null)
70
                throw new ArgumentNullException("first");
71
            if (next == null)
72
                throw new ArgumentNullException("next");
73
            Contract.EndContractBlock();
74
            Contract.Assume(TaskScheduler.Current != null);
75

    
76
            var tcs = new TaskCompletionSource<object>();
77
            first.ContinueWith(delegate
78
            {
79
                if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions);
80
                else if (first.IsCanceled) tcs.TrySetCanceled();
81
                else
82
                {
83
                    try
84
                    {
85
                        var t = next(first.Result);
86
                        if (t == null) tcs.TrySetCanceled();
87
                        else t.ContinueWith(delegate
88
                        {
89
                            if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions);
90
                            else if (t.IsCanceled) tcs.TrySetCanceled();
91
                            else tcs.TrySetResult(null);
92
                        }, TaskContinuationOptions.ExecuteSynchronously);
93
                    }
94
                    catch (Exception exc) { tcs.TrySetException(exc); }
95
                }
96
            }, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Current);
97
            return tcs.Task;
98
        }
99

    
100

    
101

    
102
        public static void ReportExceptions(this Task task,Action<AggregateException> OnError,Action OnSuccess )
103
        {
104
            if (!task.IsCompleted) throw new InvalidOperationException("The task has not completed.");
105
            if (task.IsFaulted)             
106
                task.Exception.Handle(exc=>
107
                                          {
108
                                              OnError(task.Exception);
109
                                              return true;
110
                                          }); 
111
            else
112
            {
113
                OnSuccess();
114
            }
115
        }
116

    
117
        public static bool TryRemove<T>(this ObservableConcurrentCollection<T> collection,T item) where T:class
118
        {
119
            IProducerConsumerCollection<T> items= collection;
120
            for (var i = 0; i < items.Count; i++)
121
            {
122
                T tempItem;
123
                if (!items.TryTake(out tempItem)) 
124
                    return false;
125
                if (tempItem == item) 
126
                    return true;
127
                items.TryAdd(item);
128
            }
129
            return false;
130
        }
131

    
132
        public static bool TryAdd<T>(this ObservableConcurrentCollection<T> collection,T item) where T:class
133
        {
134
            if (collection==null)
135
                throw new ArgumentNullException("collection");
136
            Contract.EndContractBlock();
137

    
138
            if (item == null)
139
                return false;
140

    
141
            IProducerConsumerCollection<T> items= collection;            
142
            return items.TryAdd(item);
143
        }
144

    
145
    }
146
}