예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
        }
예제 #5
0
        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));
            }
        }
예제 #6
0
        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;
                    }
                }
            }
        }
예제 #7
0
        public TaskEventArgs(RunningTask runningTask)
        {
            Argument.IsNotNull(() => runningTask);

            RunningTask = runningTask;
        }
예제 #8
0
 public RunningTaskInfo(Task task, RunningTask runningTask)
 {
     Task        = task;
     RunningTask = runningTask;
 }
예제 #9
0
 public RunningTaskInfo(Task task, RunningTask runningTask)
 {
     Task = task;
     RunningTask = runningTask;
 }
예제 #10
0
        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;
                    }
                }
            }
        }
예제 #11
0
        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;
        }