@@ -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