Periodic and ResourceIntensive Tasks in Windows Phone (Mango)

Introduction

In my last article, we looked at Alarms and Reminders, appetizers for the new scheduler features in the new Mango update. Today we're going to look at the entree: Background Tasks. More specifically, Periodic and ResourceIntensive Tasks (There is one for audio and transfers, we'll look at these in the next article(s)).

Differences

Let's first look at the difference between the two types of tasks and where we should use each. I'm sure by their names, you could fathom a guess as to what each is meant to do, but here are the constraints for each, summarized from their full descriptions at MSDNhttp://msdn.microsoft.com/en-us/library/hh202942(v=VS.92).aspx

Constraint

PeriodicTask

ResourceIntensiveTask

Scheduled Interval

30 minutes

Run when requirements are met

Execution duration

15 seconds

10 minutes

Power

Battery Saver mode can prevent execution

External power required

Battery must be at 90%

Other limitations

Per-device periodic agent limit

Device must be locked

Non-cellular connection required (Wi-Fi or PC)

No active phone call

These constraints must be met for your tasks to run. It is important to note that should any of these conditions no longer be met, your task will be terminated, so make sure to write your tasks with this in mind. It is ultimately up to you to choose which task best suites your situation, but it is strongly recommended keeping periodic tasks as quick as possible, while saving large synchronization tasks for a ResourceIntensiveTask. 

Similarities

Both tasks are restricted by a few universal rules. Firstly, they can't use certain APIs (Mostly UI, calling other tasks, and interacting with the device's sensors). The full list can be found at http://msdn.microsoft.com/en-us/library/hh202962(v=VS.92).aspx.  Secondly, the task may not use more than 5 MB of memory, or it will be terminated. Lastly, your tasks have an ExpirationTime (the time that the system will stop trying to execute it), which is by default 2 weeks. Anytime your application is launched, you have an opportunity to extend that time, to the 2 week maximum. 

With the prerequisites out of the way, let's look at how to use Tasks.

Use

The first step in using ScheduledTasks is to create a ScheduledAgent class. This will be invoked when your task is called. The class you write is only required to be comprised of overloading OnInvoke(ScheduledTask task), as shown below. You create this by adding a new project to the solution, selecting the new "Windows Phone Scheduled Task Agent" temple, pictured here.

Windows Phone

The project will open up and show you the template for the ScheduledAgent. Below is what I see as the bare minimum for this class.

#define DEBUG_AGENT
using Microsoft.Phone.Scheduler;

namespace ExampleAgent
{
    
public class ScheduledAgent : ScheduledTaskAgent
    {
        
protected override void OnInvoke(ScheduledTask task)
        {
            
if (task is PeriodicTask)
            {
                
// Logic for Periodic Task
            }
            
else
            {
                
// Logic for ResourceIntensiveTask
            }
            
// Use this to invoke your task much quicker when debugging
#if DEBUG_AGENT
            ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(60));
#endif
            // Tell the Scheduler we are done
            NotifyComplete();
        }
    }
}


As you can see, the "is" keyword is used to check what kind of task is calling your agent, as all tasks will call the same one per application. We also set the task to run one minute after being ran; a handy debugging feature. Finally, this code tells the system that our task is officially completed. 

The next step is to use this agent in our main Windows Phone project. Here is a method used in the example at MSDN, which shows the entire process (The procedure is the same for ResourceIntensiveTasks, just with a different class).

public partial class MainPage : PhoneApplicationPage
{
        PeriodicTask periodicTask;
        ResourceIntensiveTask resourceIntensiveTask;
 
        string periodicTaskName = "PeriodicAgent";
        string resourceIntensiveTaskName = "ResourceIntensiveAgent";

        private void StartPeriodicAgent()

        {
            periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;
 
            // If the task already exists and the IsEnabled property is false, background
            // agents have been disabled by the user
            if (periodicTask != null && !periodicTask.IsEnabled)
            {
                MessageBox.Show("Background agents for this application have been disabled by the user.");
                return;
            }
 
            // If the task already exists and background agents are enabled for the
            // application, you must remove the task and then add it again to update 
            // the schedule
            if (periodicTask != null && periodicTask.IsEnabled)
            {
                RemoveAgent(periodicTaskName);
            }

            periodicTask = new PeriodicTask(periodicTaskName);
            // The description is required for periodic agents. This is the string that the user
            // will see in the background services Settings page on the device.
            periodicTask.Description = "This demonstrates a periodic task.";
            ScheduledActionService.Add(periodicTask); 
           
// If debugging is enabled, use LaunchForTest to launch the agent in one minute.

#if(DEBUG_AGENT)
            ScheduledActionService.LaunchForTest(periodicTaskName, TimeSpan.FromSeconds(60));
#endif

}


This example first checks to see if the system allows the task to run. It then checks if the task is still scheduled, and removes it if it is. The important thing to not is that your task needs a name and description. These are what the user will see in the device's settings for background tasks. If they don't know what something is, they most likely will prevent it from running, so be descriptive.
 
 
Conclusion
 
I know this was more talking than examples, but I feel that developers need a good understanding of what they have to work with, before deciding which task we need, or if we even need them at all. For a fully fleshed out example, I highly suggest you take a look at the MSDN sample on this subject, over at http://msdn.microsoft.com/en-us/library/ff402535(v=VS.92).aspx.  While you're at it, check out the others, as they all go over new things Mango brings to the table.


Similar Articles