Wiki Navigation
- Loading...
General description
The TaskScheduler namespace provides means to schedule particular tasks. The TaskScheduler is registered with the ServiceScope and takes care of the scheduling logic required to run particular tasks at a given time or interval. The only thing your code has to do is add a task to the task scheduler and listen for due schedules on the TaskScheduler's message queue. Scheduled tasks are able to survive restarts and are stored by the TaskScheduler forever or until they are expired. To schedule a task from your code, you need to:
- Create a new Task and add it to the TaskScheduler
- Listen on the "taskscheduler" message queue
- Optionally store the TaskID to be able to remember the scheduled task between restarts
Schedule types
Before scheduling tasks it's important to understand what kind of schedules the TaskScheduler supports. You can create two schedule types:
- Time-based schedules
- Interval-based schedules
Time-based schedules
The time-based schedules run at a given time, repeatedly if configured to do so. A particular example task would be every monday on 8:00, every day on 5:55, the 5th minute of every hour on tuesday, etc. Other possibilities are upcoming friday at 7:00 (once), or the first next day at 3:00 (once). You can specify the minute, hour and weekday for these types of schedules. If you specify -1 for any of these parameters, this means every. So for example when giving -1 for hour this means every hour, and -1 for weekday means every weekday.
Valid values for minute, hour and day (weekday):
- minute: -1, 0-59
- hour: -1, 0-23
- day: -1, 0-6
Interval-based schedules
The interval-based schedules run repteatedly at a given interval, either infinite or until they are expired. The interval should be given as a positive TimeSpan. The TimeSpan should not be less than one minute, because the TaskScheduler only works with minute precision.
Task occurrence
The TaskScheduler currently accepts 4 types of occurrences:
- Once
- Repeat
- EveryStartUp
- EveryWakeUp (not implemented yet)
Interval-based schedules should always have Repeat as occurrence. Time-based schedules can have all types of occurrences.
Task expiry
All tasks can expire at a given DateTime. You can set the task expire time at creation or through the Expires property of the task. Tasks unregister themselves from the TaskScheduler when they expire.
Force schedule
When the core is not started, schedules cannot run of course. You can configure a task to force its schedule when it is due late. For example you have created a task which should run this day on 20:00. Currently it's 18:00 and you decide to stop MediaPortal. Now when you start the core again at 21:00, your schedule was due an hour ago. If you set a task to force its schedule run, it will also send a due schedule message when it is due late. You can set this through the ForceRun property of your task or at task creation.
System Wakeup
This feature needs other core parts which aren't implemented yet!
If your system is using Power Management, you can set a task to wakeup the system for a particular task. You can set this throught the WakeupSystem property of your task or at task creation. If your task isn't really required to run at a particular time, you can also opt for using the ForceRun property which makes sure the task fires when the system wakes up again.
Creating tasks
Creating a task is as simple as creating an instance of the Task class. This class provides a wealth of Constructors to immediately create the task you require, without the need to modify or set other properties. As long as you haven't submitted your task to the TaskScheduler, the ID of the task is unset. After submission to the Task Scheduler you can get the assigned ID of your task from the Task object.
Creating time-based tasks
Let's create a task that runs every day at 5:55, expires in about 7 days, forces the schedule when it's due late and wakes up the system from standby if required:
using MediaPortal.Common; using MediaPortal.Common.TaskScheduler; class SomeClass { public SomeClass() { Task task = new Task( "SomeClass", // task owner 55, // minute 5, // hour -1, // day Occurrence.Repeat, // occurrence DateTime.Now.AddDays(7), // expires true, // force run true // wakeup system ); } }
Creating interval-based tasks
Now let's create a task that runs every 40 minutes and never expires:
using MediaPortal.Common; using MediaPortal.Common.TaskScheduler; class SomeClass { public SomeClass() { Task task = new Task( "SomeClass", // task owner new TimeSpan(0, 40, 0), // interval DateTime.MaxValue, // expires false, // force run false // wakeup system ); } }
Creating at-startup / at-wakeup tasks
The at-wakeup feature needs other core parts which aren't implemented yet!
using MediaPortal.Common; using MediaPortal.Common.TaskScheduler; class SomeClass { public SomeClass() { Task task1 = new Task("SomeClass", Occurrence.EveryStartUp); Task task2 = new Task("SomeClass", Occurrence.EveryWakeUp); } }
Submitting tasks to the TaskScheduler
Before your task is processed by the TaskScheduler, you'll have to submit it to the TaskScheduler. Since the TaskScheduler is registered with the ServiceScope, you can use the ServiceScope to access the TaskScheduler:
using MediaPortal.Common; using MediaPortal.Common.TaskScheduler; class SomeClass { public SomeClass() { Task task = new Task("SomeClass", 0, 5, -1, Occurrence.Repeat); ServiceScope.Get<ITaskScheduler>().AddTask(task); } }
Getting schedule notifications from the TaskScheduler
Now that you have submitted a task to the TaskScheduler, you will probably want to receive a notification from the TaskScheduler when your scheduled task is due. You do this by registering with the "taskscheduler" message queue from the MessageBroker:
using MediaPortal.Common; using MediaPortal.Common.Messaging; using MediaPortal.Common.TaskScheduler; class SomeClass { int _myTaskID; public SomeClass() { Task task = new Task("SomeClass", 0, 5, -1, Occurrence.Repeat); ServiceScope.Get<IMessageBroker>().Get("taskscheduler").OnMessageReceive += new MessageReceivedHandler(OnMessageReceive); ServiceScope.Get<ITaskScheduler>().AddTask(task); _myTaskID = task.ID; } void OnMessageReceive(MPMessage message) { TaskMessage msg = message.Metadata["taskmessage"] as TaskMessage; if (msg.Task.Owner.Equals("SomeClass")) { switch (msg.Type) { case TaskMessageType.DUE: // perform your time-based or interval-based actions // for all your scheduled tasks here if (msg.Task.ID == _myTaskID) { // hey, our previously registered schedule is due :-) } break; case TaskMessageType.CHANGED: // act on changes to any of your scheduled tasks break; case TaskMessageType.DELETED: // act on deletion of any of your scheduled tasks break; case TaskMessageType.EXPIRED: // act on expiry of any of your scheduled tasks break; } } } }
After registering your task to the TaskScheduler, it will be kept registered even between restarts of the core. So it's a good idea to store _myTaskID in this example in your configuration for future reference to the task.
Task management
Retrieving / Updating tasks
In case you need to update your task, you can obtain your task from the TaskScheduler, change it and then pass it back to the TaskScheduler to update it. You can do this as follows:
using MediaPortal.Common; using MediaPortal.Common.TaskScheduler; class SomeClass { int _myTaskID = <taskID>; // previously submitted taskID or get it from saved settings public void ChangeMyTask(DateTime expires) { Task myTask = ServiceScope.Get<ITaskScheduler>().GetTask(_myTaskID); myTask.Expires = expires; ServiceScope.Get<ITaskScheduler>().UpdateTask(myTask); } }
Removing a task
If your module or plugin doesn't need the scheduled task anymore, it can be removed manually from the task scheduler. You just specify the ID of the task to remove.
using MediaPortal.Common; using MediaPortal.Common.TaskScheduler; class SomeClass { int _myTaskID = <taskID>; // previously submitted taskID or get it from saved settings public void RemoveMyTask() { ServiceScope.Get<ITaskScheduler>().UpdateTask(_myTaskID); } }
Obtaining all scheduled tasks from a particular owner
using MediaPortal.Common; using MediaPortal.Common.TaskScheduler; class SomeClass { public SomeClass() { List<Task> tasks = ServiceScope.Get<ITaskScheduler>().GetTasks("someowner"); foreach (Task task in tasks) { // remove all interval-based tasks from owner "someowner" if (task.Schedule.Type == ScheduleType.IntervalBased) { ServiceScope.Get<ITaskScheduler>().RemoveTask(task.ID); } } } }
This page has no comments.