The background agent for the sample is the TaskScheduler
class, which is a subclass of the ScheduledTaskAgent
class. TaskScheduler
is registered using the WMAppManifest.xml file.
As you saw earlier, a periodic task is registered in the TodoItemViewModel
class. This causes the TaskScheduler.OnInvoke
method to be called periodically. The OnInvoke
method determines what kind of task is being launched by the OS, either
periodic or resource intensive. For the to-do sample, it is always a
periodic task (see Listing 1).
LISTING 1. TaskScheduler OnInvoke
Method (excerpt)
protected override void OnInvoke(ScheduledTask task)
{
/* Detect if the task is periodic or resource intensive. */
if (task is PeriodicTask)
{
ProcessPeriodicTask();
}
else
{
ProcessResourceIntensiveTask();
}
...
NotifyComplete();
}
The main purpose of the TaskScheduler
is to refresh the shell tiles on the Start Experience, updating the
overdue status and changing the background image as required (see Listing 2).
The ProcessPeriodicTask
method retrieves all tiles for the app containing the to-do item query
string parameter. Each tile is processed by extracting the Id
of the to-do item, and then by retrieving the actual TodoItem
object using the to-do service. A new StandardTileData
object is created for the TodoItem
using the TodoTileDataCreator
, and the tile is updated.
LISTING 2. TaskScheduler ProcessPeriodicTask
Method
void ProcessPeriodicTask()
{
TodoService todoService = new TodoService();
string queryWithEquals = TodoItemIdQueryKey + "=";
IEnumerable<ShellTile> tiles = ShellTile.ActiveTiles.Where(
tile => tile.NavigationUri.ToString().Contains(queryWithEquals));
foreach (var tile in tiles)
{
/* NavigationUri.Query raises an exception on relative URIs. */
Dictionary<string, string> queryPairs
= UrlUtility.ParseQueryString(tile.NavigationUri.ToString());
string idString = queryPairs[TodoItemIdQueryKey];
int todoItemId;
if (!int.TryParse(idString, out todoItemId))
{
Debug.Assert(false, "Invalid id " + idString);
continue;
}
TodoItem todoItem;
if (!todoService.TryGetTodoItem(todoItemId, out todoItem))
{
Debug.Assert(false, "Unknown item " + idString);
continue;
}
StandardTileData tileData = TodoTileDataCreator.CreateTile(
todoItem.Description,
todoItem.DueDate);
tile.Update(tileData);
}
}
Using a scheduled task agent to
update shell tiles provides the means to engage with your users even
when your app is not running. It should be remembered, however, that
there is no guarantee that a scheduled task will run; therefore, it is
wise not to depend solely on a background task for activities critical
to the proper functioning of your app. Indeed, updating of shell tiles
should also be done within your foreground app, which is not done in
the sample.