Mobile Zone is brought to you in partnership with:

I love technology. Plain and simple. You can generally find me writing software, figuring out how to get rid of cable, playing on my Xbox, or traveling around this country speaking about software development. If you're doing something cool with technology, let me know. I'd love to hear your story about something amazing. You can find my blog at jeffblankenburg.com Jeff is a DZone MVB and is not an employee of DZone and has posted 71 posts at DZone. You can read more from them at their website. View Full User Profile

31 Days of Windows 8 | Day #12: Background Tasks

11.23.2012
| 2882 views |
  • submit to reddit

This article is Day #12 in a series called 31 Days of Windows 8.  Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.

advertisementsample

Today, we are talking about Background Tasks.  The short way to describe Background Tasks is this:

A Background Task is the code that runs when your app doesn’t.

Think of the scenarios:

  • Continue streaming audio, even when the user is running another app.
  • Update the user’s Live Tile to reflect new data.
  • Pop a Toast Notification to let the user know something important has happened.
  • Update the user’s lock screen, even when the device is locked.

Getting a Background Task established and registered with the system is a two-step process.  First, you have to register the Background Task in your package.appxmanifest file.  Once that has been done, you still need to register the events of that Task with the system from your application code, and then there are additional events to manage what happens when Background Tasks finish.  We will cover these scenarios in this article.

My first step is always to create a secondary project that will contain my Background Tasks.  This isn’t required, but it’s a nice visual separation of your code.

12-XAML-AddProject

When you create a new Project, choose “Windows Runtime Component” as the project type.

12-XAML-WindowsRuntimeComponent  By default, you are given a class named Class1.cs.  You can either rename it, or just delete it and add a new Class to the new project.  In either case, you’re going to create a Class file named TileUpdater.cs.

Now, Background Tasks must implement a very specific interface: IBackgroundTask.  It only implements one method, Run(), and this is the method that will be called when our app kicks off the Background Task.  Just to get you started, here’s what my C# looks like after implementing the interface:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
namespace BackgroundTasks
{
    public sealed class TileUpdater : IBackgroundTask
    {
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            //We will add code here later.
        }
    }
}

I’ve added a comment where our code will reside, but for now, this is a good start.

The next step in this process is to declare that we will be using Background Tasks in this application.  We do this in the package.appxmanifest file, in the Declarations section, as illustrated by the screenshot below (click to enlarge):

12-XAML-Appxmanifest

As you can see, we’ve added a declaration for Background Tasks (you will a new one of these for each Background Task you want to add to your project), and set the entry point to be BackgroundTasks.TileUpdater, our new class file.  Next, we need to register this task in our actual application, so that Windows 8 knows to run it at the appropriate times.

We’re going to take a couple of steps in this code of our MainPage.xaml.cs file, starting with checking to see if our Background Task has already been registered to the system.  I generally do this as soon as the page loads, in my OnNavigatedTo method.  I’ve create a new CheckTaskRegistration() method that checks this status for me, and sets a global Boolean value in the page.  You could certainly do this in your App.xaml.cs file as well, but for our simple purposes, this location works fine.

bool isTaskRegistered = false;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    CheckTaskRegistration();
}
private void CheckTaskRegistration()
{
    foreach (var task in BackgroundTaskRegistration.AllTasks)
    {
        if (task.Value.Name == "TileUpdater")
        {
            isTaskRegistered = true;
            break;
        }
    }
    if (!isTaskRegistered)
    {
        RegisterBackgroundTask("TileUpdater", "BackgroundTasks.TileUpdater");
    }
}

As you can see, we are looping through the BackgroundTaskRegistration.AllTasks collection, because we could have multiple Background Tasks running under our application, and in this case, I’m only interested in the one: TileUpdater.  You can also see that I’ve made a call to RegisterBackgroundTask() if the task is not currently registered.

It is up to you how you handle this case, but in my application, I want to make sure that my Background Task is always registered, and if it has been unregistered for some reason, I want to add it back in.  Here’s what my RegisterBackgroundTask() method looks like:

private void RegisterBackgroundTask(string name, string entrypoint)
{
    BackgroundTaskBuilder btb = new BackgroundTaskBuilder();
    btb.Name = name;
    btb.TaskEntryPoint = entrypoint;
    btb.SetTrigger(new SystemTrigger(SystemTriggerType.InternetAvailable, false));
    BackgroundTaskRegistration task = btb.Register();
}

You can see that I’m passing in the name and entrypoint values, but you could certainly hard code those depending on your situation.  Since this application could have multiple Background Tasks, I decided to make this construction a little simpler and pass in some parameters.

In our registration method, we create a BackgroundTaskBuilder object, set the name and entry point, and then determine a SystemTrigger that will kick our Background Task off.  In this case, I’ve chosen the easily testable InternetAvailable trigger.  To try it, we’ll be cutting off our internet access on our machine.

If you ever have a need to unregister your Background Task, it’s pretty simple.  Here’s a sample method, UnregisterBackgroundTask() that you can use to remove the Task.

private void UnregisterBackgroundTask(string name)
{
    foreach (var task in BackgroundTaskRegistration.AllTasks)
    {
        if (task.Value.Name == name)
        {
            task.Value.Unregister(true);
        }
    }
}

In this example, we loop through the Tasks that are registered again, and if we find the one with the name we’re looking for, we call its Unregister() method, confirming with the true parameter.

So we’ve worked through registering and unregistering our Background Task, and we now have specified that our application should kick off our Background Task when the time zone of the machine changes.  Let’s write some actual code in our Background Task class, and then give this thing a test.

Earlier, we created a file named TileUpdater.cs in our new Windows Runtime Component project, and we left some space to add some code to the Run() method that must be implemented as part of the IBackgroundTask interface.  Here’s what that same file looks like with code to update our Live Tile:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
namespace BackgroundTasks
{
    public sealed class TileUpdater : IBackgroundTask
    {
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            XmlDocument tileData = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquareText04);
            XmlNodeList textData = tileData.GetElementsByTagName("text");
            textData[0].InnerText = "Background updates are absolutely amazing. #31daysofwin8";
            TileNotification notification = new TileNotification(tileData);
            notification.ExpirationTime = DateTimeOffset.UtcNow.AddSeconds(30);
            TileUpdateManager.CreateTileUpdaterForApplication().Update(notification);
        }
    }
}

Obviously, we could write a similar Background Task to implement sending a Toast notification, updating the Lock Screen, or other valuable calls to web services for example.

There’s one more thing to note about Background Tasks: they’re much harder to debug than the code in your actual application.  In fact, Microsoft has written an entire article about exactly how to Debug Your Background Tasks.  I highly recommend reading it.  They have also created a quickstart tutorial called Create and Register a Background Task.

If you would like to download the working sample code from this article, click the icon below:

downloadXAML

Tomorrow, we’re going to shift gears again, and start talking about Navigation.  Specifically, how to navigate between pages in a XAML application, and pass parameters and data as part of that process.  See you then!

downloadTheTools

Published at DZone with permission of Jeff Blankenburg, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)