protected virtual Task OnTaskIsDueAsync(HTaskSchedulerEventArgs e) { if (e == null) { return(Task.CompletedTask); } return(Cancellable.CancellableRunAsync( () => TaskIsDue?.Invoke(e.Sender, e) , this.Cts.Token)); }
private void Process(IHTaskItem task) { HTaskSchedulerEventArgs evArgs = null; try { // check if task is eligible to run including retry on error status (if failed to run in an earlier attempt and the schedule // for when to retry and retry max attempts). if (!this.IsDue(task)) { return; } void RunTask() { if (this.Cts.IsCancellationRequested) { return; } // todo: threaded having continuewith to check // run status evArgs = new HTaskSchedulerEventArgs( this, task, this.Cts.Token ); // if eligible to run (and has no previous error logged), trigger synchronous event this.OnTaskIsDueAsync(evArgs) .GetAwaiter().GetResult(); } if (task.Schedule?.Repeat != null) { AtomicGate delaySwitch = new AtomicGate(); foreach (var repeatDataModel in task.Schedule?.Repeat.EnsureEnumerable()) { if (task.Schedule?.RepeatDelayInterval > 0 && !delaySwitch.TryOpen()) { if (this.Cts?.Token != null) { Task.Delay((int)task.Schedule.RepeatDelayInterval, (CancellationToken)this.Cts.Token) .GetAwaiter().GetResult(); } else { Task.Delay((int)task.Schedule.RepeatDelayInterval) .GetAwaiter().GetResult(); } } if (this.Cts.IsCancellationRequested) { return; } IEnumerable <IHTaskItem> AllChildren(IHTaskItem item) { return((item.Children?.SelectMany(x => AllChildren(x)) ?? Enumerable.Empty <IHTaskItem>()).Append(item)); } foreach (var child in AllChildren(task) //.Where(x => x.Vars?.Custom == null) ) { child.Vars.Custom = repeatDataModel; } RunTask(); } } else { RunTask(); } // log successful run, and reset retry on error logic in case it was previously set. this.TimeLog[task.UniqueKey].LastExecuted = DateTime.Now; this.TimeLog[task.UniqueKey].ErrorCount = 0; this.TimeLog[task.UniqueKey].LastError = null; this.TimeLog.Save(); } catch (Exception ex) { // catch errors within the thread, and check if retry on error is enabled // if enabled, don't throw exception, trigger OnErrorEvent async, then log error retry attempts and last error this.OnErrorAsync(new HTaskSchedularErrorEventArgs(this, ex, evArgs)); if (task.Schedule.RetryAttemptsAfterError == null) { throw; } this.TimeLog[task.UniqueKey].ErrorCount++; this.TimeLog[task.UniqueKey].LastError = DateTime.Now; this.TimeLog.Save(); } }