Scheduling Background Agents in Windows Phone 7.1 Mango


Scheduled Tasks & Background Agents allows apps to run in background in Windows Phone while the app is not running in foreground. There are two types of Scheduled Tasks referenced called Periodic Tasks & ResourceIntensive Tasks which helps to implement background agent scaling.

  • Periodic Tasks: Periodic agents run for a small amount of time on a regular recurring interval. Typical scenarios for this type of task include uploading the device’s location and performing small amounts of data synchronization.
  • Resource-Intensive Tasks: This tasks works for long period of time when the phone meets a set of requirements relating to processor activity, power source, and network connection. A typical scenario for this type of task is synchronizing large amounts of data to the phone while it is not being actively used by the user.
  • The Background  Agent LifeCycle for Windows Phone:  The app can have at least of one type of Scheduled tasks either Periodic Tasks or Scheduled Tasks or even both. So the schedule on which the agent runs depends on which type of task it is registered as.

There are some constraints features on both of Periodic Tasks & Resource-Intensive Tasks . For details Click here.

  • Implement Background Tasks for Windows Phone 7.1 Mango : In order to implement it you need to a Windows Phone application project in VS 2010 SP1 from Silverlight for Windows Phone template.

  • Add a new Schedule Task agent Project to add resources for Schedule agent tasks in Windows Phone app.

  • In order to access the Schedule Task apps in Foreground app , we need to add reference of ScheduleTaskAgent1 Project in ScheduledTask project by clicking on add reference-> Project dialog.

  • Now, add the following code in ScheduleAgent.cs file in the ScheduleTaskAgent1 project.

#define

DEBUG_AGENT

using  System.Windows;

using Microsoft.Phone.Scheduler;

using  Microsoft.Phone.Scheduler;

using  Microsoft.Phone.Shell;

using  System;

namespace ScheduledTaskAgent1

{

public class ScheduledAgent : ScheduledTaskAgent

{

private static volatile bool _classInitialized;

///<remarks>

/// ScheduledAgent constructor, initializes the UnhandledException handler

///</remarks>

public ScheduledAgent()

{

if (!_classInitialized)

{

_classInitialized = true;

// Subscribe to the managed exception handler

Deployment.Current.Dispatcher.BeginInvoke(delegate

{

Application.Current.UnhandledException += ScheduledAgent_UnhandledException;

});

}

}

/// Code to execute on Unhandled Exceptions

private void ScheduledAgent_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)

{

if (System.Diagnostics.Debugger.IsAttached)

{

// An unhandled exception has occurred; break into the debugger

System.Diagnostics.

Debugger.Break();

}

}

///<summary>

/// Agent that runs a scheduled task

///</summary>

///<param name=”task”>

/// The invoked task

///</param>

///<remarks>

/// This method is called when a periodic or resource intensive task is invoked

///</remarks>

protected overridevoid OnInvoke(ScheduledTask task)

{

//TODO: Add code to perform your task in background

string toastMessage = “Hello WP7”;

if (task isPeriodicTask)

{

toastMessage = “Periodic task running.”;

}

else

{

toastMessage = “Resource-intensive task running.”;

}

// The toast will not be shown if the foreground application is running.

ShellToast toast = newShellToast();

toast.Title = “Background Agent Sample”;

toast.Content = toastMessage;

toast.Show();

#if

DEBUG_AGENT

ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(60));

#endif

// Call NotifyComplete to let the system know is done working .

NotifyComplete();

}

}

}

  • So, Next to build the Forgeound App Project , so move to MainPage.xaml in ScheduleTask Project of Windows Phone.

MainPage.Xaml:  Modify the code inside the Grid name called ContentPanel.

<Grid x:Name=”ContentPanel” Grid.Row=”1″ Margin=”12,0,12,0″>

<StackPanel>

<StackPanel Orientation=”Vertical” Name=”PeriodicStackPanel” Margin=”0,0,0,40″>

<TextBlock Text=”Periodic Agent” Style=”{StaticResource PhoneTextTitle2Style}” />

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”name:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding Name}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”is enabled” VerticalAlignment=”Center” Style=”{StaticResource PhoneTextAccentStyle}” />

<CheckBox Name=”PeriodicCheckBox” IsChecked=”{Binding IsEnabled}” Checked=”PeriodicCheckBox_Checked” Unchecked=”PeriodicCheckBox_Unchecked” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”is scheduled:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding IsScheduled}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”last scheduled time:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding LastScheduledTime}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”expiration time:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding ExpirationTime}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”last exit reason:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding LastExitReason}” />

</StackPanel>

</StackPanel>

<StackPanel Orientation=”Vertical” Name=”ResourceIntensiveStackPanel” Margin=”0,0,0,40″>

<TextBlock Text=”Resource-intensive Agent” Style=”{StaticResource PhoneTextTitle2Style}” />

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”name:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding Name}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”is enabled” VerticalAlignment=”Center” Style=”{StaticResource PhoneTextAccentStyle}” />

<CheckBox Name=”ResourceIntensiveCheckBox” IsChecked=”{Binding IsEnabled}” Checked=”ResourceIntensiveCheckBox_Checked” Unchecked=”ResourceIntensiveCheckBox_Unchecked” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”is scheduled:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding IsScheduled}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”last scheduled time:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding LastScheduledTime}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”expiration time:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding ExpirationTime}” />

</StackPanel>

<StackPanel Orientation=”Horizontal”>

<TextBlock Text=”last exit reason:” Style=”{StaticResource PhoneTextAccentStyle}” />

<TextBlock Text=”{Binding LastExitReason}” />

</StackPanel>

</StackPanel>

</StackPanel>

</Grid>

</Grid>

  • Add the following code in MainPage.xaml.cs:

MainPage.xaml.cs:

#define DEBUG_AGENT

using System;

using  System.Collections.Generic;

using System.Linq;

using  System.Net;

using  System.Windows;

using  System.Windows.Controls;

using  System.Windows.Documents;

using  System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using  System.Windows.Shapes;

using  Microsoft.Phone.Controls;

using  Microsoft.Phone.Scheduler;

namespace ScheduledTask

{

public partial class MainPage : PhoneApplicationPage

{

PeriodicTask periodicTask;

ResourceIntensiveTask resourceIntensiveTask;

string periodicTaskName = “PeriodicAgent”;

string resourceIntensiveTaskName = “ResourceIntensiveAgent”;

public bool agentsAreEnabled = true;

// Constructor

public MainPage()

{

InitializeComponent();

}

private void StartPeriodicAgent()

{

agentsAreEnabled = true;

periodicTask = ScheduledActionService.Find(periodicTaskName) asPeriodicTask;

if (periodicTask != null)

{

RemoveAgent(periodicTaskName);

}

periodicTask = newPeriodicTask(periodicTaskName);

periodicTask = newPeriodicTask(periodicTaskName);

periodicTask.Description = “This demonstrates a periodic task.”;

// Place the call to add in a try block in case the user has disabled agents.

try

{

ScheduledActionService.Add(periodicTask);

PeriodicStackPanel.DataContext = periodicTask;

// If debugging is enabled , use LaunchForTest to launch the agent in one minutes

#if

(DEBUG_AGENT)

ScheduledActionService.LaunchForTest(periodicTaskName, TimeSpan.FromSeconds(60));

#endif

}

catch (InvalidOperationException exception)

{

if (exception.Message.Contains(“BNS Error: The action is disabled”))

{

MessageBox.Show(“Bakcground agents for this application have been disabled by the user.”);

agentsAreEnabled = false;

PeriodicCheckBox.IsChecked = false;

}

if (exception.Message.Contains(“BNS Error: The maximum number of ScheduledActions of this type have already been added.”))

{

// No user action required.

}

PeriodicCheckBox.IsChecked = false;

}

catch (SchedulerServiceException)

{

PeriodicCheckBox.IsChecked =false;

}

}

private void StartResourceIntensiveAgent()

{

agentsAreEnabled = true;

resourceIntensiveTask =  ScheduledActionService.Find(resourceIntensiveTaskName) asResourceIntensiveTask;

if (resourceIntensiveTask != null)

{

RemoveAgent(resourceIntensiveTaskName);

}

resourceIntensiveTask = newResourceIntensiveTask(resourceIntensiveTaskName);

try

{

ScheduledActionService.Add(resourceIntensiveTask);

ResourceIntensiveStackPanel.DataContext = resourceIntensiveTask;

#if

(DEBUG_AGENT)

ScheduledActionService.LaunchForTest(resourceIntensiveTaskName, TimeSpan.FromSeconds(60));

#endif

}

catch (InvalidOperationException exception)

{

if (exception.Message.Contains(“BNS Error: The action is disabled”))

{

MessageBox.Show(“Background agents for this application have been disabled by the user.”);

agentsAreEnabled = false;

}

ResourceIntensiveCheckBox.IsChecked = false;

}

catch (SchedulerServiceException)

{

ResourceIntensiveCheckBox.IsChecked = false;

}

}

bool ignoreCheckBoxEvents = false;

private void PeriodicCheckBox_Checked(object sender, RoutedEventArgs e)

{

if (ignoreCheckBoxEvents)

return;

StartPeriodicAgent();

}

private void PeriodicCheckBox_Unchecked(object sender, RoutedEventArgs e)

{

if (ignoreCheckBoxEvents)

     return;

RemoveAgent(periodicTaskName);

}

private void ResourceIntensiveCheckBox_Checked(object sender, RoutedEventArgs e)

{

if (ignoreCheckBoxEvents)

return;

RemoveAgent(resourceIntensiveTaskName);

}

private void ResourceIntensiveCheckBox_Unchecked(object sender, RoutedEventArgs e)

{

if (ignoreCheckBoxEvents)

return;

RemoveAgent(resourceIntensiveTaskName);

}

private void RemoveAgent(string name)

{

    try

{

ScheduledActionService.Remove(name);

}

catch (Exception)

{

}

}

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)

{

ignoreCheckBoxEvents = true;

periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;

     if (periodicTask != null)

{

PeriodicStackPanel.DataContext = periodicTask;

}

resourceIntensiveTask = ScheduledActionService.Find(resourceIntensiveTaskName) as ResourceIntensiveTask;

   if (resourceIntensiveTask != null)

{

ResourceIntensiveStackPanel.DataContext = resourceIntensiveTask;

}

ignoreCheckBoxEvents = false;

}

  • Now the Debug the app in Windows Phone 7.1 Mango emulator & check the background app agent running as Schedule Tasks.

  •    The Background apps schedule time with Periodic Agent on Windows Phone.

  • Enable Background schedule to receive toast notification as foreground process from background activity apps. Check to see the Toast notification tile on Mango screen as foreground process.

Advertisements

About Anindita
Anindita Basak is working as Big Data Cloud Consultant in Microsoft. Worked in multiple MNCs as Developer & Senior Developer on Microsoft Azure, Data Platform, IoT & BI , Data Visualization, Data warehousing & ETL & of course in Hadoop platform.She played both as FTE & v- employee in Azure platform teams of Microsoft.Passionate about .NET , Java, Python & Data Science. She is also an active Big Data & Cloud Trainer & would love share her experience in IT Training Industry. She is an author, forum contributor, blogger & technical reviewer of various books on Big Data Hadoop, HDInsight, IoT & Data Science, SQL Server PDW & PowerBI.

5 Responses to Scheduling Background Agents in Windows Phone 7.1 Mango

  1. Great post! I will give a try in this way. Thanks

  2. aaronnz says:

    Hi Anindita. You sample is great but I was wondering if I can have something running in the background tasks that gets details from an RSS feed. For example updating a live tile with a new news article from an RSS feed. How would I go about doing this? Do you have any sample around this please?

  3. @aaronnz, I can help you here… I have sample code for that. but I am using Twitter JSON to update back tile.

    How to send?

    Thank you!

    • dinchy87 says:

      Hi you said you have a code sample to download my rss in the background and display the last title on the back of the live tile?! and can this sample do this with my app too? i used webclient to downlaod my rss but only when my app starts, i want not to add something like you have that will update my back of the live tile.

      and is there any quick solution that the backgroundagent checks if its the same title of the last rss feed the app downlaoded, and if its not then that it displays a toast message?! i dont know how to do that but i would like to 😦 i have not used anything to store this info like the last feed title and then that the background agent do this. can you help me with that?

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

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

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: