using System; using System.Threading; namespace Implab { public class ActionChainTaskBase : AbstractTask { readonly Func m_error; readonly Func m_cancel; protected ActionChainTaskBase(Func error, Func cancel, bool autoCancellable) { m_error = error; m_cancel = cancel; if (autoCancellable) CancellationRequested(CancelOperation); } public void Reject(Exception error) { if (LockCancelation()) HandleErrorInternal(error); } public override void CancelOperation(Exception reason) { if (LockCancelation()) // отмена вызвана до начала выполнения задачи HandleCancelInternal(reason); } protected void HandleCancelInternal(Exception reason) { if (m_cancel != null) { try { // вызываем обработчик отмены var p = m_cancel(reason); p.On(SetResult, HandleErrorInternal, SetCancelledInternal); // сообщаем асинхронной операции, что клиент уже не хочет получать результат // т.е. если он инициировал отмену, задача отменилась, вызвался обрабочик отмены // отбработчику сообщили, что результат уже не нужен и уже сам обработчик решает // отдавать ли результат или подтвердить отмену (или вернуть ошибку). CancellationRequested(p.Cancel); } catch (Exception err) { SetErrorInternal(err); } } else { SetCancelledInternal(reason); } } protected void HandleErrorInternal(Exception error) { if (m_error != null) { try { var p = m_error(error); p.On(SetResult, SetErrorInternal, SetCancelledInternal); CancellationRequested(p.Cancel); } catch (Exception err) { SetErrorInternal(err); } } else { SetErrorInternal(error); } } } }