| @@ -0,0 +1,45 | |||||
|
|
1 | using System; | |||
|
|
2 | using System.Threading; | |||
|
|
3 | ||||
|
|
4 | namespace Implab { | |||
|
|
5 | /// <summary> | |||
|
|
6 | /// Базовый класс для реализации задачь. Задача представляет собой некторое | |||
|
|
7 | /// действие, которое можно иницировать и обработать результат его выполнения | |||
|
|
8 | /// в виде обещания, для этого оно реализует интерфейс <see cref="IPromise"/>. | |||
|
|
9 | /// </summary> | |||
|
|
10 | /// <remarks> | |||
|
|
11 | /// Данный класс определяет стандартное поведение при обработки результатов, в частности | |||
|
|
12 | /// обработку <see cref="System.OperationCanceledException"/> и <see cref="PromiseTransientException"/> | |||
|
|
13 | /// </remarks> | |||
|
|
14 | public abstract class AbstractTask : AbstractPromise { | |||
|
|
15 | int m_cancelationLock; | |||
|
|
16 | ||||
|
|
17 | /// <summary> | |||
|
|
18 | /// Получает эксклюзивное право отмены задания, используется для отмены задания до начала его выполнения. | |||
|
|
19 | /// </summary> | |||
|
|
20 | /// <returns><c>true</c>, if cancelation was locked, <c>false</c> otherwise.</returns> | |||
|
|
21 | protected bool LockCancelation() { | |||
|
|
22 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); | |||
|
|
23 | } | |||
|
|
24 | ||||
|
|
25 | ||||
|
|
26 | ||||
|
|
27 | protected void SetErrorInternal(Exception error) { | |||
|
|
28 | // unwrap | |||
|
|
29 | while (error is PromiseTransientException && error.InnerException != null) | |||
|
|
30 | error = error.InnerException; | |||
|
|
31 | ||||
|
|
32 | if (error is OperationCanceledException) | |||
|
|
33 | SetCancelled(error); | |||
|
|
34 | else | |||
|
|
35 | SetError(error); | |||
|
|
36 | } | |||
|
|
37 | ||||
|
|
38 | protected void SetCancelledInternal(Exception reason) { | |||
|
|
39 | SetCancelled( | |||
|
|
40 | reason == null ? new OperationCanceledException() : reason is OperationCanceledException ? reason : new OperationCanceledException(null, reason) | |||
|
|
41 | ); | |||
|
|
42 | } | |||
|
|
43 | } | |||
|
|
44 | } | |||
|
|
45 | ||||
| @@ -0,0 +1,36 | |||||
|
|
1 | using System; | |||
|
|
2 | using System.Threading; | |||
|
|
3 | ||||
|
|
4 | namespace Implab { | |||
|
|
5 | public abstract class AbstractTask<T> : AbstractPromise<T> { | |||
|
|
6 | int m_cancelationLock; | |||
|
|
7 | ||||
|
|
8 | /// <summary> | |||
|
|
9 | /// Получает эксклюзивное право отмены задания, используется для отмены задания до начала его выполнения. | |||
|
|
10 | /// </summary> | |||
|
|
11 | /// <returns><c>true</c>, if cancelation was locked, <c>false</c> otherwise.</returns> | |||
|
|
12 | protected bool LockCancelation() { | |||
|
|
13 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); | |||
|
|
14 | } | |||
|
|
15 | ||||
|
|
16 | ||||
|
|
17 | ||||
|
|
18 | protected void SetErrorInternal(Exception error) { | |||
|
|
19 | // unwrap | |||
|
|
20 | while (error is PromiseTransientException && error.InnerException != null) | |||
|
|
21 | error = error.InnerException; | |||
|
|
22 | ||||
|
|
23 | if (error is OperationCanceledException) | |||
|
|
24 | SetCancelled(error); | |||
|
|
25 | else | |||
|
|
26 | SetError(error); | |||
|
|
27 | } | |||
|
|
28 | ||||
|
|
29 | protected void SetCancelledInternal(Exception reason) { | |||
|
|
30 | SetCancelled( | |||
|
|
31 | reason == null ? new OperationCanceledException() : reason is OperationCanceledException ? reason : new OperationCanceledException(null, reason) | |||
|
|
32 | ); | |||
|
|
33 | } | |||
|
|
34 | } | |||
|
|
35 | } | |||
|
|
36 | ||||
| @@ -21,8 +21,10 namespace Implab { | |||||
| 21 | if (m_task != null && LockCancelation()) { |
|
21 | if (m_task != null && LockCancelation()) { | |
| 22 | try { |
|
22 | try { | |
| 23 | var p = m_task(); |
|
23 | var p = m_task(); | |
| 24 |
p.On(SetResult, HandleErrorInternal, |
|
24 | p.On(SetResult, HandleErrorInternal, HandleCancelInternal); | |
| 25 | CancellationRequested(p.Cancel); |
|
25 | CancellationRequested(p.Cancel); | |
|
|
26 | } catch (OperationCanceledException reason){ | |||
|
|
27 | HandleCancelInternal(reason); | |||
| 26 | } catch(Exception err) { |
|
28 | } catch(Exception err) { | |
| 27 | HandleErrorInternal(err); |
|
29 | HandleErrorInternal(err); | |
| 28 | } |
|
30 | } | |
| @@ -2,12 +2,10 | |||||
| 2 | using System.Threading; |
|
2 | using System.Threading; | |
| 3 |
|
3 | |||
| 4 | namespace Implab { |
|
4 | namespace Implab { | |
| 5 |
public class ActionChainTaskBase : Abstract |
|
5 | public class ActionChainTaskBase : AbstractTask { | |
| 6 | readonly Func<Exception, IPromise> m_error; |
|
6 | readonly Func<Exception, IPromise> m_error; | |
| 7 | readonly Func<Exception, IPromise> m_cancel; |
|
7 | readonly Func<Exception, IPromise> m_cancel; | |
| 8 |
|
8 | |||
| 9 | int m_cancelationLock; |
|
|||
| 10 |
|
||||
| 11 | protected ActionChainTaskBase(Func<Exception, IPromise> error, Func<Exception, IPromise> cancel, bool autoCancellable) { |
|
9 | protected ActionChainTaskBase(Func<Exception, IPromise> error, Func<Exception, IPromise> cancel, bool autoCancellable) { | |
| 12 | m_error = error; |
|
10 | m_error = error; | |
| 13 | m_cancel = cancel; |
|
11 | m_cancel = cancel; | |
| @@ -21,55 +19,44 namespace Implab { | |||||
| 21 | } |
|
19 | } | |
| 22 |
|
20 | |||
| 23 | public override void CancelOperation(Exception reason) { |
|
21 | public override void CancelOperation(Exception reason) { | |
| 24 |
if (LockCancelation()) |
|
22 | if (LockCancelation()) | |
| 25 | if (!(reason is OperationCanceledException)) |
|
23 | // отмена вызвана до начала выполнения задачи | |
| 26 | reason = reason != null ? new OperationCanceledException(null, reason) : new OperationCanceledException(); |
|
24 | HandleCancelInternal(reason); | |
| 27 |
|
|
25 | } | |
| 28 | if (m_cancel != null) { |
|
26 | ||
| 29 | try { |
|
27 | protected void HandleCancelInternal(Exception reason) { | |
| 30 | m_cancel(reason).On(SetResult, HandleErrorInternal, HandleCancelInternal); |
|
28 | if (m_cancel != null) { | |
| 31 |
|
|
29 | try { | |
| 32 | HandleErrorInternal(err); |
|
30 | // вызываем обработчик отмены | |
| 33 |
|
|
31 | var p = m_cancel(reason); | |
| 34 | } else { |
|
32 | p.On(SetResult, HandleErrorInternal, SetCancelledInternal); | |
| 35 | HandleErrorInternal(reason); |
|
33 | // сообщаем асинхронной операции, что клиент уже не хочет получать результат | |
|
|
34 | // т.е. если он инициировал отмену, задача отменилась, вызвался обрабочик отмены | |||
|
|
35 | // отбработчику сообщили, что результат уже не нужен и уже сам обработчик решает | |||
|
|
36 | // отдавать ли результат или подтвердить отмену (или вернуть ошибку). | |||
|
|
37 | CancellationRequested(p.Cancel); | |||
|
|
38 | } catch (Exception err) { | |||
|
|
39 | HandleErrorInternal(err); | |||
| 36 | } |
|
40 | } | |
|
|
41 | } else { | |||
|
|
42 | HandleErrorInternal(reason ?? new OperationCanceledException()); | |||
| 37 | } |
|
43 | } | |
| 38 | } |
|
44 | } | |
| 39 |
|
45 | |||
| 40 |
void Handle |
|
46 | protected void HandleErrorInternal(Exception error) { | |
| 41 | if (!(reason is OperationCanceledException)) |
|
|||
| 42 | reason = reason != null ? new OperationCanceledException(null, reason) : new OperationCanceledException(); |
|
|||
| 43 | HandleErrorInternal(reason); |
|
|||
| 44 | } |
|
|||
| 45 |
|
||||
| 46 | void HandleErrorInternal(Exception error) { |
|
|||
| 47 | if (m_error != null) { |
|
47 | if (m_error != null) { | |
| 48 | try { |
|
48 | try { | |
| 49 | var p = m_error(error); |
|
49 | var p = m_error(error); | |
| 50 | p.On(SetResult, SetError, SetCancelled); |
|
50 | p.On(SetResult, SetErrorInternal, SetCancelledInternal); | |
| 51 | CancellationRequested(p.Cancel); |
|
51 | CancellationRequested(p.Cancel); | |
| 52 | } catch (Exception err) { |
|
52 | } catch (Exception err) { | |
| 53 |
error |
|
53 | SetErrorInternal(error); | |
| 54 | } |
|
54 | } | |
| 55 | } else { |
|
55 | } else { | |
| 56 | SetErrorInternal(error); |
|
56 | SetErrorInternal(error); | |
| 57 | } |
|
57 | } | |
| 58 | } |
|
58 | } | |
| 59 |
|
59 | |||
| 60 | void SetErrorInternal(Exception error) { |
|
|||
| 61 | while (error is PromiseTransientException) |
|
|||
| 62 | error = error.InnerException; |
|
|||
| 63 |
|
||||
| 64 | if (error is OperationCanceledException) |
|
|||
| 65 | SetCancelled(error); |
|
|||
| 66 | else |
|
|||
| 67 | SetError(error); |
|
|||
| 68 | } |
|
|||
| 69 |
|
||||
| 70 | protected bool LockCancelation() { |
|
|||
| 71 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); |
|
|||
| 72 | } |
|
|||
| 73 | } |
|
60 | } | |
| 74 | } |
|
61 | } | |
| 75 |
|
62 | |||
| @@ -12,8 +12,10 namespace Implab { | |||||
| 12 | if (m_task != null && LockCancelation()) { |
|
12 | if (m_task != null && LockCancelation()) { | |
| 13 | try { |
|
13 | try { | |
| 14 | var p = m_task(value); |
|
14 | var p = m_task(value); | |
| 15 |
p.On(SetResult, HandleErrorInternal, |
|
15 | p.On(SetResult, HandleErrorInternal, HandleCancelInternal); | |
| 16 | CancellationRequested(p.Cancel); |
|
16 | CancellationRequested(p.Cancel); | |
|
|
17 | } catch (OperationCanceledException reason) { | |||
|
|
18 | HandleCancelInternal(reason); | |||
| 17 | } catch(Exception err) { |
|
19 | } catch(Exception err) { | |
| 18 | HandleErrorInternal(err); |
|
20 | HandleErrorInternal(err); | |
| 19 | } |
|
21 | } | |
| @@ -12,6 +12,8 namespace Implab { | |||||
| 12 | try { |
|
12 | try { | |
| 13 | m_task(); |
|
13 | m_task(); | |
| 14 | SetResult(); |
|
14 | SetResult(); | |
|
|
15 | } catch(OperationCanceledException reason) { | |||
|
|
16 | HandleCancelInternal(reason); | |||
| 15 | } catch(Exception err) { |
|
17 | } catch(Exception err) { | |
| 16 | HandleErrorInternal(err); |
|
18 | HandleErrorInternal(err); | |
| 17 | } |
|
19 | } | |
| @@ -1,13 +1,10 | |||||
| 1 | using System; |
|
1 | using System; | |
| 2 | using System.Threading; |
|
|||
| 3 |
|
2 | |||
| 4 | namespace Implab { |
|
3 | namespace Implab { | |
| 5 |
public class ActionTaskBase : Abstract |
|
4 | public class ActionTaskBase : AbstractTask { | |
| 6 | readonly Action<Exception> m_cancel; |
|
5 | readonly Action<Exception> m_cancel; | |
| 7 | readonly Action<Exception> m_error; |
|
6 | readonly Action<Exception> m_error; | |
| 8 |
|
7 | |||
| 9 | int m_cancelationLock; |
|
|||
| 10 |
|
||||
| 11 | protected ActionTaskBase( Action<Exception> error, Action<Exception> cancel, bool autoCancellable) { |
|
8 | protected ActionTaskBase( Action<Exception> error, Action<Exception> cancel, bool autoCancellable) { | |
| 12 | m_error = error; |
|
9 | m_error = error; | |
| 13 | m_cancel = cancel; |
|
10 | m_cancel = cancel; | |
| @@ -21,37 +18,36 namespace Implab { | |||||
| 21 | HandleErrorInternal(error); |
|
18 | HandleErrorInternal(error); | |
| 22 | } |
|
19 | } | |
| 23 |
|
20 | |||
|
|
21 | public override void CancelOperation(Exception reason) { | |||
|
|
22 | if (LockCancelation()) | |||
|
|
23 | HandleCancelInternal(reason); | |||
|
|
24 | } | |||
|
|
25 | ||||
| 24 | protected void HandleErrorInternal(Exception error) { |
|
26 | protected void HandleErrorInternal(Exception error) { | |
| 25 | if (m_error != null) { |
|
27 | if (m_error != null) { | |
| 26 | try { |
|
28 | try { | |
| 27 | m_error(error); |
|
29 | m_error(error); | |
| 28 | SetResult(); |
|
30 | SetResult(); | |
| 29 | } catch(Exception err) { |
|
31 | } catch(Exception err) { | |
| 30 | SetError(err); |
|
32 | SetErrorInternal(err); | |
| 31 | } |
|
33 | } | |
| 32 | } else { |
|
34 | } else { | |
| 33 | SetError(error); |
|
35 | SetErrorInternal(error); | |
| 34 | } |
|
36 | } | |
| 35 | } |
|
37 | } | |
| 36 |
|
38 | |||
| 37 |
p |
|
39 | protected void HandleCancelInternal(Exception error) { | |
| 38 |
if ( |
|
40 | if (m_cancel != null) { | |
| 39 |
|
|
41 | try { | |
| 40 |
|
|
42 | m_cancel(error); | |
| 41 |
|
|
43 | SetResult(); | |
| 42 | SetResult(); |
|
44 | } catch(Exception err) { | |
| 43 |
|
|
45 | HandleErrorInternal(err); | |
| 44 | HandleErrorInternal(err); |
|
|||
| 45 | } |
|
|||
| 46 | } else { |
|
|||
| 47 | SetCancelled(reason); |
|
|||
| 48 | } |
|
46 | } | |
|
|
47 | } else { | |||
|
|
48 | HandleErrorInternal(error ?? new OperationCanceledException()); | |||
| 49 | } |
|
49 | } | |
| 50 | } |
|
50 | } | |
| 51 |
|
||||
| 52 | protected bool LockCancelation() { |
|
|||
| 53 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); |
|
|||
| 54 | } |
|
|||
| 55 | } |
|
51 | } | |
| 56 | } |
|
52 | } | |
| 57 |
|
53 | |||
| @@ -12,6 +12,8 namespace Implab { | |||||
| 12 | try { |
|
12 | try { | |
| 13 | m_task(value); |
|
13 | m_task(value); | |
| 14 | SetResult(); |
|
14 | SetResult(); | |
|
|
15 | } catch(OperationCanceledException reason) { | |||
|
|
16 | HandleCancelInternal(reason); | |||
| 15 | } catch(Exception err) { |
|
17 | } catch(Exception err) { | |
| 16 | HandleErrorInternal(err); |
|
18 | HandleErrorInternal(err); | |
| 17 | } |
|
19 | } | |
| @@ -137,10 +137,6 namespace Implab.Components { | |||||
| 137 | } |
|
137 | } | |
| 138 | } |
|
138 | } | |
| 139 | throw new PromiseTransientException(e); |
|
139 | throw new PromiseTransientException(e); | |
| 140 | }, |
|
|||
| 141 | r => { |
|
|||
| 142 | // handle cancellation as exception |
|
|||
| 143 | throw new OperationCanceledException("The operation has been cancelled", r); |
|
|||
| 144 | } |
|
140 | } | |
| 145 | ); |
|
141 | ); | |
| 146 |
|
142 | |||
| @@ -194,7 +190,13 namespace Implab.Components { | |||||
| 194 | if (current == null) { |
|
190 | if (current == null) { | |
| 195 | stop.Resolve(); |
|
191 | stop.Resolve(); | |
| 196 | } else { |
|
192 | } else { | |
| 197 | current.On(stop.Resolve, stop.Reject, e => stop.Resolve()); |
|
193 | // связваем текущую операцию с операцией остановки | |
|
|
194 | current.On( | |||
|
|
195 | stop.Resolve, // если текущая операция заверщилась, то можно начинать остановку | |||
|
|
196 | stop.Reject, // если текущая операция дала ошибку - то все плохо, нельзя продолжать | |||
|
|
197 | e => stop.Resolve() // если текущая отменилась, то можно начинать остановку | |||
|
|
198 | ); | |||
|
|
199 | // посылаем текущей операции сигнал остановки | |||
| 198 | current.Cancel(); |
|
200 | current.Cancel(); | |
| 199 | } |
|
201 | } | |
| 200 | } |
|
202 | } | |
| @@ -13,8 +13,10 namespace Implab { | |||||
| 13 | if (m_task != null && LockCancelation()) { |
|
13 | if (m_task != null && LockCancelation()) { | |
| 14 | try { |
|
14 | try { | |
| 15 | var operation = m_task(); |
|
15 | var operation = m_task(); | |
| 16 |
operation.On(SetResult, HandleErrorInternal, |
|
16 | operation.On(SetResult, HandleErrorInternal, HandleCancelInternal); | |
| 17 | CancellationRequested(operation.Cancel); |
|
17 | CancellationRequested(operation.Cancel); | |
|
|
18 | } catch (OperationCanceledException reason) { | |||
|
|
19 | HandleCancelInternal(reason); | |||
| 18 | } catch (Exception err) { |
|
20 | } catch (Exception err) { | |
| 19 | HandleErrorInternal(err); |
|
21 | HandleErrorInternal(err); | |
| 20 | } |
|
22 | } | |
| @@ -1,13 +1,10 | |||||
| 1 | using System; |
|
1 | using System; | |
| 2 | using System.Threading; |
|
|||
| 3 |
|
2 | |||
| 4 | namespace Implab { |
|
3 | namespace Implab { | |
| 5 |
public class FuncChainTaskBase<TResult> : Abstract |
|
4 | public class FuncChainTaskBase<TResult> : AbstractTask<TResult> { | |
| 6 | readonly Func<Exception, IPromise<TResult>> m_error; |
|
5 | readonly Func<Exception, IPromise<TResult>> m_error; | |
| 7 | readonly Func<Exception, IPromise<TResult>> m_cancel; |
|
6 | readonly Func<Exception, IPromise<TResult>> m_cancel; | |
| 8 |
|
7 | |||
| 9 | int m_cancelationLock; |
|
|||
| 10 |
|
||||
| 11 | protected FuncChainTaskBase( Func<Exception, IPromise<TResult>> error, Func<Exception, IPromise<TResult>> cancel, bool autoCancellable) { |
|
8 | protected FuncChainTaskBase( Func<Exception, IPromise<TResult>> error, Func<Exception, IPromise<TResult>> cancel, bool autoCancellable) { | |
| 12 | m_error = error; |
|
9 | m_error = error; | |
| 13 | m_cancel = cancel; |
|
10 | m_cancel = cancel; | |
| @@ -21,37 +18,36 namespace Implab { | |||||
| 21 | } |
|
18 | } | |
| 22 |
|
19 | |||
| 23 | public override void CancelOperation(Exception reason) { |
|
20 | public override void CancelOperation(Exception reason) { | |
| 24 |
if (LockCancelation()) |
|
21 | if (LockCancelation()) | |
| 25 | if (m_cancel != null) { |
|
22 | HandleCancelInternal(reason); | |
| 26 | try { |
|
|||
| 27 | m_cancel(reason).On(SetResult, HandleErrorInternal, SetCancelled); |
|
|||
| 28 | } catch (Exception err) { |
|
|||
| 29 | HandleErrorInternal(err); |
|
|||
| 30 | } |
|
|||
| 31 | } else { |
|
|||
| 32 | SetCancelled(reason); |
|
|||
| 33 | } |
|
|||
| 34 | } |
|
|||
| 35 |
|
||||
| 36 | } |
|
23 | } | |
| 37 |
|
24 | |||
| 38 | protected void HandleErrorInternal(Exception error) { |
|
25 | protected void HandleErrorInternal(Exception error) { | |
| 39 | if (m_error != null) { |
|
26 | if (m_error != null) { | |
| 40 | try { |
|
27 | try { | |
| 41 |
var |
|
28 | var p = m_error(error); | |
| 42 |
|
29 | p.On(SetResult, SetErrorInternal, SetCancelledInternal); | ||
| 43 | operation.On(SetResult, SetError, SetCancelled); |
|
30 | CancellationRequested(p.Cancel); | |
| 44 | CancellationRequested(operation.Cancel); |
|
|||
| 45 | } catch(Exception err) { |
|
31 | } catch(Exception err) { | |
| 46 | SetError(err); |
|
32 | SetErrorInternal(err); | |
| 47 | } |
|
33 | } | |
| 48 | } else { |
|
34 | } else { | |
| 49 | SetError(error); |
|
35 | SetErrorInternal(error); | |
| 50 | } |
|
36 | } | |
| 51 | } |
|
37 | } | |
| 52 |
|
38 | |||
| 53 |
protected |
|
39 | protected void HandleCancelInternal(Exception reason) { | |
| 54 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); |
|
40 | if (m_cancel != null) { | |
|
|
41 | try { | |||
|
|
42 | var p = m_cancel(reason); | |||
|
|
43 | p.On(SetResult, HandleErrorInternal, SetCancelledInternal); | |||
|
|
44 | CancellationRequested(p.Cancel); | |||
|
|
45 | } catch (Exception err) { | |||
|
|
46 | HandleErrorInternal(err); | |||
|
|
47 | } | |||
|
|
48 | } else { | |||
|
|
49 | HandleErrorInternal(reason ?? new OperationCanceledException()); | |||
|
|
50 | } | |||
| 55 | } |
|
51 | } | |
| 56 | } |
|
52 | } | |
| 57 | } |
|
53 | } | |
| @@ -14,6 +14,8 namespace Implab { | |||||
| 14 | var operation = m_task(value); |
|
14 | var operation = m_task(value); | |
| 15 | operation.On(SetResult, HandleErrorInternal, SetCancelled); |
|
15 | operation.On(SetResult, HandleErrorInternal, SetCancelled); | |
| 16 | CancellationRequested(operation.Cancel); |
|
16 | CancellationRequested(operation.Cancel); | |
|
|
17 | } catch (OperationCanceledException reason) { | |||
|
|
18 | HandleCancelInternal(reason); | |||
| 17 | } catch (Exception err) { |
|
19 | } catch (Exception err) { | |
| 18 | HandleErrorInternal(err); |
|
20 | HandleErrorInternal(err); | |
| 19 | } |
|
21 | } | |
| @@ -13,6 +13,8 namespace Implab { | |||||
| 13 | if (m_task != null && LockCancelation()) { |
|
13 | if (m_task != null && LockCancelation()) { | |
| 14 | try { |
|
14 | try { | |
| 15 | SetResult(m_task()); |
|
15 | SetResult(m_task()); | |
|
|
16 | } catch(OperationCanceledException reason) { | |||
|
|
17 | HandleCancelInternal(reason); | |||
| 16 | } catch(Exception err) { |
|
18 | } catch(Exception err) { | |
| 17 | HandleErrorInternal(err); |
|
19 | HandleErrorInternal(err); | |
| 18 | } |
|
20 | } | |
| @@ -1,13 +1,10 | |||||
| 1 | using System; |
|
1 | using System; | |
| 2 | using System.Threading; |
|
|||
| 3 |
|
2 | |||
| 4 | namespace Implab { |
|
3 | namespace Implab { | |
| 5 |
public class FuncTaskBase<TResult> : Abstract |
|
4 | public class FuncTaskBase<TResult> : AbstractTask<TResult> { | |
| 6 | readonly Func<Exception, TResult> m_cancel; |
|
5 | readonly Func<Exception, TResult> m_cancel; | |
| 7 | readonly Func<Exception, TResult> m_error; |
|
6 | readonly Func<Exception, TResult> m_error; | |
| 8 |
|
7 | |||
| 9 | int m_cancelationLock; |
|
|||
| 10 |
|
||||
| 11 | protected FuncTaskBase( Func<Exception, TResult> error, Func<Exception, TResult> cancel, bool autoCancellable) { |
|
8 | protected FuncTaskBase( Func<Exception, TResult> error, Func<Exception, TResult> cancel, bool autoCancellable) { | |
| 12 | m_error = error; |
|
9 | m_error = error; | |
| 13 | m_cancel = cancel; |
|
10 | m_cancel = cancel; | |
| @@ -26,30 +23,30 namespace Implab { | |||||
| 26 | try { |
|
23 | try { | |
| 27 | SetResult(m_error(error)); |
|
24 | SetResult(m_error(error)); | |
| 28 | } catch(Exception err) { |
|
25 | } catch(Exception err) { | |
| 29 | SetError(err); |
|
26 | SetErrorInternal(err); | |
| 30 | } |
|
27 | } | |
| 31 | } else { |
|
28 | } else { | |
| 32 | SetError(error); |
|
29 | SetErrorInternal(error); | |
| 33 | } |
|
30 | } | |
| 34 | } |
|
31 | } | |
| 35 |
|
32 | |||
| 36 | public override void CancelOperation(Exception reason) { |
|
33 | public override void CancelOperation(Exception reason) { | |
| 37 |
if (LockCancelation()) |
|
34 | if (LockCancelation()) | |
| 38 | if (m_cancel != null) { |
|
35 | HandleCancelInternal(reason); | |
| 39 | try { |
|
36 | } | |
| 40 | SetResult(m_cancel(reason)); |
|
37 | ||
| 41 | } catch (Exception err) { |
|
38 | protected void HandleCancelInternal(Exception reason) { | |
| 42 | HandleErrorInternal(err); |
|
39 | if (m_cancel != null) { | |
| 43 |
|
|
40 | try { | |
| 44 | } else { |
|
41 | SetResult(m_cancel(reason)); | |
| 45 | SetCancelled(reason); |
|
42 | } catch (Exception err) { | |
|
|
43 | HandleErrorInternal(err); | |||
| 46 | } |
|
44 | } | |
|
|
45 | } else { | |||
|
|
46 | HandleErrorInternal(reason ?? new OperationCanceledException()); | |||
| 47 | } |
|
47 | } | |
| 48 | } |
|
48 | } | |
| 49 |
|
49 | |||
| 50 | protected bool LockCancelation() { |
|
|||
| 51 | return 0 == Interlocked.CompareExchange(ref m_cancelationLock, 1, 0); |
|
|||
| 52 | } |
|
|||
| 53 | } |
|
50 | } | |
| 54 | } |
|
51 | } | |
| 55 |
|
52 | |||
| @@ -12,7 +12,9 namespace Implab { | |||||
| 12 | if (m_task != null && LockCancelation()) { |
|
12 | if (m_task != null && LockCancelation()) { | |
| 13 | try { |
|
13 | try { | |
| 14 | SetResult(m_task(value)); |
|
14 | SetResult(m_task(value)); | |
| 15 |
} catch |
|
15 | } catch(OperationCanceledException reason) { | |
|
|
16 | HandleCancelInternal(reason); | |||
|
|
17 | } catch(Exception err) { | |||
| 16 | HandleErrorInternal(err); |
|
18 | HandleErrorInternal(err); | |
| 17 | } |
|
19 | } | |
| 18 | } |
|
20 | } | |
| @@ -193,6 +193,8 | |||||
| 193 | <Compile Include="Automaton\AutomatonConst.cs" /> |
|
193 | <Compile Include="Automaton\AutomatonConst.cs" /> | |
| 194 | <Compile Include="Automaton\RegularExpressions\RegularDFA.cs" /> |
|
194 | <Compile Include="Automaton\RegularExpressions\RegularDFA.cs" /> | |
| 195 | <Compile Include="Components\LazyAndWeak.cs" /> |
|
195 | <Compile Include="Components\LazyAndWeak.cs" /> | |
|
|
196 | <Compile Include="AbstractTask.cs" /> | |||
|
|
197 | <Compile Include="AbstractTaskT.cs" /> | |||
| 196 | </ItemGroup> |
|
198 | </ItemGroup> | |
| 197 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> |
|
199 | <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> | |
| 198 | <ItemGroup /> |
|
200 | <ItemGroup /> | |
General Comments 0
You need to be logged in to leave comments.
Login now
