private void RescheduleRecurringTask(RunningTask runningTask) { // Note: it's important to start possible recurring tasks outside the loop var scheduledTask = runningTask.ScheduledTask; if (scheduledTask.Recurring.HasValue) { // Note: we might have overridden the interval in the clone, so we need to clone it first var newScheduledTask = scheduledTask.Clone(); var startDate = _timeService.CurrentDateTime; if (newScheduledTask.Recurring.HasValue) { // Use new recurring value startDate = startDate.Add(newScheduledTask.Recurring.Value); } else { // Use old recurring value startDate = startDate.Add(scheduledTask.Recurring.Value); } Log.Debug($"Task {scheduledTask} is a recurring task, rescheduling a copy at '{startDate}'"); newScheduledTask.Start = startDate; AddScheduledTask(newScheduledTask); } }
private void OnRunningTaskCompleted(Task task) { RunningTask runningTask = null; CancellationTokenSource cancellationTokenSource = null; var cancellationToken = default(CancellationToken); var exception = task.Exception; var stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Task completed, searching for existing running task"); stringBuilder.AppendLine($" * Canceled: {task.IsCanceled}"); stringBuilder.AppendLine($" * Completed: {task.IsCompleted}"); stringBuilder.AppendLine($" * Faulted: {task.IsFaulted}"); stringBuilder.AppendLine($" * Exception: {exception}"); Log.Debug(stringBuilder.ToString()); lock (_lock) { for (var i = 0; i < _runningTasks.Count; i++) { var possibleRunningTask = _runningTasks[i]; if (ReferenceEquals(possibleRunningTask.Task, task)) { runningTask = possibleRunningTask.RunningTask; _runningTasks.RemoveAt(i); cancellationTokenSource = possibleRunningTask.RunningTask.CancellationTokenSource; cancellationToken = cancellationTokenSource.Token; cancellationTokenSource.Dispose(); break; } } } if (runningTask is not null) { Log.Debug($"Found task '{runningTask}' for the completed task"); if (runningTask.ScheduledTask.ScheduleRecurringTaskAfterTaskExecutionHasCompleted) { RescheduleRecurringTask(runningTask); } if (!task.IsCanceled && !cancellationTokenSource.IsCancellationRequested && !_cancelledTokenSources.Contains(cancellationToken)) { TaskCompleted?.Invoke(this, new TaskEventArgs(runningTask)); } } }
private bool StartTask(IScheduledTask scheduledTask) { lock (_lock) { if (!IsEnabled) { return(false); } Log.Debug("Starting task {0}", scheduledTask); var runningTask = new RunningTask(scheduledTask, _timeService.CurrentDateTime); #pragma warning disable 4014 // Note: don't await, we are a scheduler. var task = TaskShim.Run(async() => await scheduledTask.InvokeAsync(), runningTask.CancellationTokenSource.Token); task.ContinueWith(OnRunningTaskCompleted); #pragma warning restore 4014 Log.Debug("Started task {0}", scheduledTask); var completed = task.IsCompleted; if (completed) { // Shortcut mode TaskStarted.SafeInvoke(this, new TaskEventArgs(runningTask)); OnRunningTaskCompleted(task); } else { _runningTasks.Add(new RunningTaskInfo(task, runningTask)); TaskStarted.SafeInvoke(this, new TaskEventArgs(runningTask)); } } // Note: it's important to start possible recurring tasks outside the loop if (scheduledTask.Recurring.HasValue) { var startDate = _timeService.CurrentDateTime.Add(scheduledTask.Recurring.Value); Log.Debug("Task {0} is a recurring task, rescheduling a copy at '{1}'", scheduledTask, startDate); var newScheduledTask = (IScheduledTask)scheduledTask.Clone(); newScheduledTask.Start = startDate; AddScheduledTask(newScheduledTask); } return(true); }
public static bool IsExpired(this RunningTask runningTask, ITimeService timeService) { Argument.IsNotNull(() => runningTask); Argument.IsNotNull(() => timeService); var duration = timeService.CurrentDateTime - runningTask.Started; if (duration > runningTask.ScheduledTask.MaximumDuration) { return(true); } return(false); }
private void StartTask(IScheduledTask scheduledTask) { Task task = null; RunningTask runningTask = null; lock (_lock) { if (!IsEnabled) { return; } Log.Debug($"Starting task {scheduledTask}"); runningTask = new RunningTask(scheduledTask, _timeService.CurrentDateTime); #pragma warning disable 4014 // Note: don't await, we are a scheduler task = TaskShim.Run(async() => await scheduledTask.InvokeAsync(), runningTask.CancellationTokenSource.Token); task.ContinueWith(OnRunningTaskCompleted); #pragma warning restore 4014 Log.Debug($"Started task {scheduledTask}"); } if (!scheduledTask.ScheduleRecurringTaskAfterTaskExecutionHasCompleted) { // Schedule immediately, even though task is still running RescheduleRecurringTask(runningTask); } var completed = task.IsCompleted; if (completed) { // Shortcut mode TaskStarted?.Invoke(this, new TaskEventArgs(runningTask)); OnRunningTaskCompleted(task); } else { _runningTasks.Add(new RunningTaskInfo(task, runningTask)); TaskStarted?.Invoke(this, new TaskEventArgs(runningTask)); } }
private void TerminateTask(RunningTask runningTask) { Log.Debug($"Terminating task {runningTask}"); lock (_lock) { for (var i = 0; i < _runningTasks.Count; i++) { if (ReferenceEquals(_runningTasks[i].RunningTask, runningTask)) { _cancelledTokenSources.Add(runningTask.CancellationTokenSource.Token); runningTask.CancellationTokenSource.Cancel(); TaskCanceled?.Invoke(this, new TaskEventArgs(runningTask)); return; } } } }
public TaskEventArgs(RunningTask runningTask) { Argument.IsNotNull(() => runningTask); RunningTask = runningTask; }
public RunningTaskInfo(Task task, RunningTask runningTask) { Task = task; RunningTask = runningTask; }
private void TerminateTask(RunningTask runningTask) { Log.Debug("Terminating task {0}", runningTask); lock (_lock) { for (int i = 0; i < _runningTasks.Count; i++) { if (ReferenceEquals(_runningTasks[i].RunningTask, runningTask)) { _cancelledTokenSources.Add(runningTask.CancellationTokenSource.Token); runningTask.CancellationTokenSource.Cancel(); TaskCanceled.SafeInvoke(this, new TaskEventArgs(runningTask)); return; } } } }
private bool StartTask(IScheduledTask scheduledTask) { lock (_lock) { if (!IsEnabled) { return false; } Log.Debug("Starting task {0}", scheduledTask); var runningTask = new RunningTask(scheduledTask, _timeService.CurrentDateTime); #pragma warning disable 4014 // Note: don't await, we are a scheduler. var task = TaskShim.Run(async () => await scheduledTask.InvokeAsync(), runningTask.CancellationTokenSource.Token); task.ContinueWith(OnRunningTaskCompleted); #pragma warning restore 4014 Log.Debug("Started task {0}", scheduledTask); var completed = task.IsCompleted; if (completed) { // Shortcut mode TaskStarted.SafeInvoke(this, new TaskEventArgs(runningTask)); OnRunningTaskCompleted(task); } else { _runningTasks.Add(new RunningTaskInfo(task, runningTask)); TaskStarted.SafeInvoke(this, new TaskEventArgs(runningTask)); } } // Note: it's important to start possible recurring tasks outside the loop if (scheduledTask.Recurring.HasValue) { var startDate = _timeService.CurrentDateTime.Add(scheduledTask.Recurring.Value); Log.Debug("Task {0} is a recurring task, rescheduling a copy at '{1}'", scheduledTask, startDate); var newScheduledTask = (IScheduledTask)scheduledTask.Clone(); newScheduledTask.Start = startDate; AddScheduledTask(newScheduledTask); } return true; }