Random geekery since 2005.

Husband, father, programmer, speaker, writer, blogger, podcaster, collector, traveler, golfer.

31 Days of Mango | Day #25: Background Agents

Written in

by

Day25-BackgroundAgentsDay24-ProfilerToolDay23-ExecutionModelDay22-AppConnectDay21-Sockets

This article is Day #25 in a series called 31 Days of Mango, and was written by guest author Gary Johnson.  Gary can be reached on Twitter at @GaryGJohnson.

Today we’re going to take a look at one of the multitasking capabilities new to Windows Phone 7.5. The complete multitasking picture is comprised of several new features:

  • Background Agents
  • Background File Transfer
  • Background Audio Playback
  • Scheduled Notifications
  • Fast Application Switching

Here we will focus on Background Agents. While the file transfer and audio playback tasks cover specific scenarios, they do not allow for custom code to be executed. That is where Background Agents come in.

There are two types of Background Agents: Periodic and Resource Intensive. Resource Intensive agents are meant for tasks that will consume a large amount of system resources and come with several limitations for when they can be run. Periodic agents run more frequently and with less restriction, but are meant for tasks that are light on resource consumption. To fully understand the different limitations and benefits of each, refer to the MSDN page.

A periodic task might do something short and simple, such as refresh an RSS feed or update your live tile. A resource intensive task might do something that requires a lot of time and bandwidth, such as syncing or caching large amounts of data from a cloud service.

We are going to make a Periodic Agent that will update your application live tile with the last time the custom task was run.

Getting Started

Launch Visual Studio and create a new project. Under Silverlight for Windows Phone, select Windows Phone Application. Name it “MyAgentApp”.

clip_image002

You’ve now created the main application. It will be responsible for two things:

1) Having a live tile that the Background Agent can update with information

2) Starting and stopping the Background Agent

The Background Agent itself must live in its own special project. Add a new project to your solution, selecting Windows Phone Scheduled Task Agent. Name it MyAgent. This project will contain your custom code that will run in the background and update the live tile.

clip_image004

Finally, and this is important, go to the MyAgentApp project and add a project reference to MyAgent. This will allow you to register your agent from within the application. Also, notice the entry this automatically created in WMAppManifest.xml:

<Tasks>
      <DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
      <ExtendedTask Name="BackgroundTask">
        <BackgroundServiceAgent Specifier="ScheduledTaskAgent" Name="MyAgent" Source="MyAgent" Type="MyAgent.ScheduledAgent" />
      </ExtendedTask>
    </Tasks>
 

Creating the Application

Now it’s time to actually wire everything up. Open MainPage.xaml and add two buttons, one for starting the agent, and the other for stopping the agent:

<StackPanel VerticalAlignment="Center">
        <Button Content="Start Background Agent"
               Click="StartButton_Click"/>
        <Button Content="Stop Background Agent"
               Click="StopButton_Click"/> 
    </StackPanel>
 

 

In MainPage.xaml.cs, wire up the buttons to start and stop the agent:

private const string TASK_NAME = "MyAgent";

private void StartButton_Click(object sender, RoutedEventArgs e)
{
    StartAgent();
}

private void StopButton_Click(object sender, RoutedEventArgs e)
{
    StopAgentIfStarted();
}

private void StartAgent()
{
    StopAgentIfStarted();

    PeriodicTask task = new PeriodicTask(TASK_NAME);
    task.Description = "This is our custom agent for Day 25 – Background Agents";
    ScheduledActionService.Add(task);
#if DEBUG
    // If we’re debugging, attempt to start the task immediately
    ScheduledActionService.LaunchForTest(TASK_NAME, new TimeSpan(0, 0, 1));
#endif
}

private void StopAgentIfStarted()
{
    if (ScheduledActionService.Find(TASK_NAME) != null)
    {
        ScheduledActionService.Remove(TASK_NAME);
    }
}
 

 

Notice that to create our custom agent, we are creating a new PeriodicTask. We then use the name as an identifier when finding and stopping the agent. Notice also that we specified PeriodicTask.Description – this is a required field and will appear in Settings | Background Tasks under the name of our application.

Create the Background Agent

In the MyAgent project, open ScheduledAgent.cs and add the following code:

protected override void OnInvoke(ScheduledTask task)
{
    UpdateAppTile(GetLastUpdatedTimeMessage());
}

private string GetLastUpdatedTimeMessage()
{
    return string.Format("Last Updated: {0}", DateTime.Now);
}

private void UpdateAppTile(string message)
{
    ShellTile appTile = ShellTile.ActiveTiles.First();
    if (appTile != null)
    {
        StandardTileData tileData = new StandardTileData
        {
            BackContent = message
        };

        appTile.Update(tileData);
    }
}
 

ScheduledAgent has one important method to override – OnInvoke. This is where your agent will execute its background task. If your task is complete and you no longer need your agent to run, you can call NotifyComplete() to signal that the task completed successfully or Abort() to signal that you are cancelling your task. To keep the task running at an interval, simply do not call either, which is what we are doing here.

Running the Application

Now that our application is ready to go, deploy it to the device emulator or Windows Phone and run the application. Click the button to start the background agent. Leave the application and find it in your list of applications. Tap and hold on the application and choose “pin to start”. When you view the tile on your start page you should eventually see the application tile flip around, revealing the last time it was updated.

clip_image005

Summary

So, today we created our own custom Background Agent that updates a live tile. When making Background Agents of your own, keep in mind what we covered:

  • Background Agents allow you to execute custom code while your application is not running
  • There are two types of Background Agents – Periodic and Resource Intensive
  • Periodic tasks are for tasks that have low resource consumption, and as a result have fewer restrictions than Resource Intensive tasks
  • Background Agents need their own project, which should be added as a project reference to the application that will start the agent
  • In your agent you need to override OnInvoke()
  • When your task is completed you need to call NotifyComplete() or Abort()

To download a complete Windows Phone project that uses all of the code and concepts from above, click the Download Code button below:

download

Tomorrow we are going to look at another multitasking feature called Background File Transfer that will allow us to download or upload files while our application is not running.  See you then!

toolsbutton

Tags

17 responses to “31 Days of Mango | Day #25: Background Agents”

  1. […] 31 Days of Mango | Day #25: Background Agents – Jeff Blankenburg shares the next part of his 31 days of Mango Series, this time a guest post from Gary Johnson looking at the creation of background agents in your Windows Phone applications to allow your application to continue to perform certain operations when it is not active on the screen. […]

  2. […] Der Originalartikel befindet sich hier: Day #25: Background Agents. […]

  3. […] 31 Days of Mango | Day #25: Background Agents […]

  4. […] Esta es una traducción de Day 25: Background Agents, puedes encontrarlo aquí en su versión origin… […]

  5. Rob Streno Avatar
    Rob Streno

    Good article. One callout, though. In the code snippet:

    ShellTile appTile = ShellTile.ActiveTiles.First();
    if (appTile != null) . . .

    Shouldn’t that be FirstOrDefault()? I believe using First() there will throw an exception if the collection is empty.

    1. jeffblankenburg Avatar
      jeffblankenburg

      First is actually only used for updating the primary Live Tile, which always exists, even when the user hasn’t pinned the app to the Home Screen. For updating any other tile, you’ll want to be certain that the tile exists before you update it.

      1. Rob Streno Avatar
        Rob Streno

        Reasonable. It makes the “if(appTile != null)” redundant, then.

  6. […] For more information on Windows Phone 7 Background Agents see: Background Agents Tutorial […]

  7. Pertric Avatar
    Pertric

    when i write
    ShellTile appTile = ShellTile.ActiveTiles.First(); in code it shows me error like “Error 1 ‘System.Collections.Generic.IEnumerable’ does not contain a definition for ‘First’ and no extension method ‘First’ accepting a first argument of type ‘System.Collections.Generic.IEnumerable’ could be found (are you missing a using directive or an assembly reference?)

    for that what to do ?

    1. Jessy Avatar
      Jessy

      getting error ShellTile appTile = ShellTile.ActiveTiles.First(); in this Line . Will you pls help me to solve out it . thanks in advance !!

      1. jeffblankenburg Avatar
        jeffblankenburg

        Try adding this to the top of your page:

        using System.Linq;

    2. jeffblankenburg Avatar
      jeffblankenburg

      Try adding this to the top of your page:

      using System.Linq;

      That should solve your problem.

  8. Yama Avatar
    Yama

    You say that ” To keep the task running at an interval, simply do not call either (NotifyComplete, Abort) , which is what we are doing here.” I understand that call either will terminate the agent
    But in the Audio Player Agent sample on MSDN, they call NotifyComplete everytime a PlayState changed, so that the agent is terminated many times, but I see the sample runs well

    Why is that ? Thanks

  9. […] tried another expriment. I created a new project, and copy/pasted code from http://www.jeffblankenburg.com/2011/11/25/31-days-of-mango-day-25-background-agents/ to see if I could debug the app. I did have to make a few minor changes to the code that Jeff […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

%d bloggers like this: