Scheduler
Scheduler copied to clipboard
Disable/remove task
Hello! Tell me how to disable/remove task, created by interval/every method? This need to me for stopping execution task without restart sheduller... For example I may throw spatial exception from body of task, which cancelled schedulling this task in a future...
Hi,
I will be also interested in how to disable or remove particular task that is already set. How can I refer to each particular task in the scheduler?
BR,
Krzysztof
Yes I agree this feature is required. I have some choices on how to implement it and would love any suggestions. I'll begin work on it some time soon.
Hi, Maybe it could based on unique id of each task or applied name? Then probably the time of execution, execution function and the name/uid is necessary to pass when adding to the pool. And to remove the task we could refer by its name to point it.
I am not sure if this is the simplest way - but maybe worth of consider.
In my application I need to define some schedules that could for example switchON the device and then switchOFF. For this I need for example use two separate tasks "at" type, or if it is recurring action two "cron" tasks. I was thinking to build some object as schedule for example "Schedule(ScheduleName, timeOn, timeOff)" and in the background launch two separate tasks .at(dateON, OnAction) and .at(dateOFF, OffAction). When they are run at once they will be deleted. But when I have recurrent schedule and I am trying to use .cron(dateON, OnAction) and .cron(dateOFF, OffAction) I have no reference to those created tasks and later on I could have problem when user will decide to delete those tasks.
Hi!
Disabling task by id is not safely. Because any code block may be called method of disabling task by random id without guarantee of disabling specific task.
I suggest throw exception from specific task who needed to disabling. And Scheduller was catch exception in manage_tasks()
like this
try{ task->f(); }catch(SchedullerDisableException e){ end_of_tasks_to_run.insert(task); }
And task may be like this
std::atomic<bool> flag; s.in(1min, []() { if(flag) std::cout << "in one minute" << std::endl; else throw SchedullerDisableException(); });
Hi,
Thanks, I agree that this could be a way. I am currently trying to test what you suggest. One question, I suppose that end_of_tasks_to_run is some kind of container? How to delete the task from the task to do list? EDIT: end_of_tasks_to_run does not have insert member function. EDIT: calling the exception on my side is just causing that the action is not executed on schedule period - it could be way of enabling/disabling task. When catching the exception I am trying to call some my function delete_task to remove the task totally from execution queue (from tasks). It looks like that: void delete_task(std::shared_ptr<Task> &t) { std::cout << "Here place delete action" << std::endl;
for(auto it = tasks.begin(); it != tasks.end(); it++){
if(it->second == t){
std::cout << "The element found for time " << '\n';
tasks.erase(it->first, it->second);
}
}
}
but it seems it is never executed. My manage_task looks as follow:
` void manage_tasks() { std::lock_guardstd::mutex l(lock); auto end_of_tasks_to_run = tasks.upper_bound(Clock::now()); std::shared_ptrBosma::Task &task = (*(tasks.begin())).second;
try {
// if there are any tasks to be run and removed
if (end_of_tasks_to_run != tasks.begin()) {
// keep track of tasks that will be re-added
decltype(tasks) recurred_tasks;
// for all tasks that have been triggered
for (auto i = tasks.begin(); i != end_of_tasks_to_run; ++i) {
task = (*i).second;
if (task->interval) {
// if it's an interval task, only add the task back after f() is completed
threads.push([this, task](int) {
task->f();
// no risk of race-condition,
// add_task() will wait for manage_tasks() to release lock
add_task(task->get_new_time(), task);
});
} else {
threads.push([task](int) {
task->f();
});
// calculate time of next run and add the new task to the tasks to be recurred
if (task->recur)
recurred_tasks.emplace(task->get_new_time(), std::move(task));
}
}
// remove the completed tasks
tasks.erase(tasks.begin(), end_of_tasks_to_run);
// re-add the tasks that are recurring
for (auto &task : recurred_tasks)
tasks.emplace(task.first, std::move(task.second));
}
}
catch(SchedulerDisableException e)
{
std::cout << "here call the method to remove the particular task" << std::endl;
delete_task(task);
}
} ` Do you have any idea how to force it to work?
BR,
Krzysztof.