diff --git a/Implab/AbstractEvent.cs b/Implab/AbstractEvent.cs
--- a/Implab/AbstractEvent.cs
+++ b/Implab/AbstractEvent.cs
@@ -77,19 +77,14 @@ namespace Implab {
/// Исключение возникшее при выполнении операции
/// Данное обещание уже выполнено
protected void SetError(Exception error) {
- while (error is PromiseTransientException)
- error = error.InnerException;
-
- var isCancel = error is OperationCanceledException;
-
if (BeginTransit()) {
- m_error = isCancel ? error.InnerException : error;
- CompleteTransit(isCancel ? CANCELLED_STATE : REJECTED_STATE);
+ m_error = error;
+ CompleteTransit(REJECTED_STATE);
Signal();
} else {
WaitTransition();
- if (!isCancel || m_state == SUCCEEDED_STATE)
+ if (m_state == SUCCEEDED_STATE)
throw new InvalidOperationException("The promise is already resolved");
}
}
@@ -140,11 +135,11 @@ namespace Implab {
case SUCCEEDED_STATE:
return;
case CANCELLED_STATE:
- throw new OperationCanceledException();
+ throw new OperationCanceledException("The operation has been cancelled", m_error);
case REJECTED_STATE:
throw new TargetInvocationException(m_error);
default:
- throw new ApplicationException(String.Format("Invalid promise state {0}", m_state));
+ throw new ApplicationException(String.Format("The promise state {0} is invalid", m_state));
}
}
#endregion
diff --git a/Implab/AbstractPromise.cs b/Implab/AbstractPromise.cs
--- a/Implab/AbstractPromise.cs
+++ b/Implab/AbstractPromise.cs
@@ -134,8 +134,8 @@ namespace Implab {
}
protected void SetResult() {
- BeginSetResult();
- EndSetResult();
+ if(BeginSetResult())
+ EndSetResult();
}
}
}
diff --git a/Implab/ActionChainTaskBase.cs b/Implab/ActionChainTaskBase.cs
--- a/Implab/ActionChainTaskBase.cs
+++ b/Implab/ActionChainTaskBase.cs
@@ -20,34 +20,51 @@ namespace Implab {
HandleErrorInternal(error);
}
-
-
public override void CancelOperation(Exception reason) {
if (LockCancelation()) {
+ if (!(reason is OperationCanceledException))
+ reason = reason != null ? new OperationCanceledException(null, reason) : new OperationCanceledException();
+
if (m_cancel != null) {
try {
- m_cancel(reason).On(SetResult, SetError, SetCancelled);
+ m_cancel(reason).On(SetResult, HandleErrorInternal, HandleCancelInternal);
} catch (Exception err) {
HandleErrorInternal(err);
}
} else {
- SetCancelled(reason);
+ HandleErrorInternal(reason);
}
}
}
- protected void HandleErrorInternal(Exception error) {
+ void HandleCancelInternal(Exception reason) {
+ if (!(reason is OperationCanceledException))
+ reason = reason != null ? new OperationCanceledException(null, reason) : new OperationCanceledException();
+ HandleErrorInternal(reason);
+ }
+
+ void HandleErrorInternal(Exception error) {
if (m_error != null) {
try {
var p = m_error(error);
- p.On(SetResult,SetError,SetCancelled);
+ p.On(SetResult, SetError, SetCancelled);
CancellationRequested(p.Cancel);
} catch (Exception err) {
- SetError(err);
+ error = err;
}
} else {
+ SetErrorInternal(error);
+ }
+ }
+
+ void SetErrorInternal(Exception error) {
+ while (error is PromiseTransientException)
+ error = error.InnerException;
+
+ if (error is OperationCanceledException)
+ SetCancelled(error);
+ else
SetError(error);
- }
}
protected bool LockCancelation() {
diff --git a/Implab/Components/RunnableComponent.cs b/Implab/Components/RunnableComponent.cs
--- a/Implab/Components/RunnableComponent.cs
+++ b/Implab/Components/RunnableComponent.cs
@@ -139,14 +139,7 @@ namespace Implab.Components {
throw new PromiseTransientException(e);
},
r => {
- lock(m_stateMachine) {
- if (m_pending == promise) {
- Move(Commands.Fail);
- m_pending = null;
- m_lastError = new OperationCanceledException("The operation has been cancelled", r);
- }
-
- }
+ // handle cancellation as exception
throw new OperationCanceledException("The operation has been cancelled", r);
}
);
@@ -201,7 +194,7 @@ namespace Implab.Components {
if (current == null) {
stop.Resolve();
} else {
- current.On(stop.Resolve, stop.Reject, stop.CancelOperation);
+ current.On(stop.Resolve, stop.Reject, e => stop.Resolve());
current.Cancel();
}
}