• Blog
  • Info Support
  • Career
  • Training
  • International Group
  • Info Support
  • Blog
  • Career
  • Training
  • International Group
  • Search
logo InfoSupport
  • Latest blogs
  • Popular blogs
  • Experts
      • All
      • Bloggers
      • Speakers
  • Meet us
  • About us
    • nl
    • en
    • .NET
    • 3D printing
    • Advanced Analytics
    • Agile
    • Akka
    • Alexa
    • Algorithms
    • Api's
    • Architectuur
    • Artificial Intelligence
    • ATDD
    • Augmented Reality
    • AWS
    • Azure
    • Big Data
    • Blockchain
    • Business Intelligence
    • Chatbots
    • Cloud
    • Code Combat
    • Cognitive Services
    • Communicatie
    • Containers
    • Continuous Delivery
    • CQRS
    • Cyber Security
    • Dapr
    • Data
    • Data & Analystics
    • Data Science
    • Data Warehousing
    • Databricks
    • DataOps
    • Developers life
    • DevOps
    • Digital Days
    • Digital Twin
    • Docker
    • eHealth
    • Enterprise Architecture
    • Event Sourcing
    • Hacking
    • Infrastructure & Hosting
    • Innovatie
    • Integration
    • Internet of Things
    • Java
    • Machine Learning
    • Microservices
    • Microsoft
    • Microsoft Bot Framework
    • Microsoft Data Platform
    • Mobile Development
    • Mutation Testing
    • Open source
    • Pepper
    • Power BI
    • Privacy & Ethiek
    • Python
    • Quality Assistance & Test
    • Quality Assurance & Test
    • Requirements Management
    • Scala
    • Scratch
    • Security
    • SharePoint
    • Software Architecture
    • Software development
    • Software Factory
    • SQL Server
    • SSL
    • Start-up
    • Startup thinking
    • Stryker
    • Test Quality
    • Testing
    • TLS
    • TypeScript
    • Various
    • Web Development
    • Web-scale IT
    • Xamarin
    • All
    • Bloggers
    • Speakers
Home » Multi tasking in Windows Phone 7.1
  • Multi tasking in Windows Phone 7.1

    • By Alex van Beek
    • Various 11 years ago
    • Various 0 comments
    • Various Various
    Multi tasking in Windows Phone 7.1

    One of the coolest features in Windows Phone 7.1 is the new multi tasking feature (next to the new LINQ to SQL support of course). In this article I’ll show you how this works.

    Background

    It is important to understand how multi tasking in Windows Phone 7.1 is implemented. I first thought that I could have some kind of background service running, comparable to a background service in Windows. Well, this isn’t the case. Multi tasking in Windows Phone 7.1 is so called “Scheduled Multi Tasking”. This means that I can define a piece of code (we’ll get to this later) and the operating system is then responsible for scheduling this piece of code. How often and when this piece of code is run is dependant on multiple factors:

    • The kind of code to run.
    • The state of the device.
    • Available resources.
    • And so on.

    Depending on the factors outlined above, Windows Phone 7.1 will run your piece of code or not. This means for certain pieces of code, that they may never be run. Windows Phone 7.1 supports two kinds of code that you can schedule to run in the background, these two kinds of code are represented by the following classes:

    • PeriodicTask
    • ResourceIntensiveTask

    Depending on the type of task you choose, the schedule and the constraints that the tasks must adhere to, differ. These are the constraints for a PeriodicTask:

    • MemoryCap: 5MB.
    • Scheduled Interval: 30 minutes, but the execution time can drift by 10 minutes.
    • Scheduled Duration: 15 seconds.
    • Battery Save Mode can prevent execution.
    • There is a limit per device how many PeriodicTasks can be scheduled. This can be as low as six.

    These are the constraints for a so called ResourceIntensiveTask:

    • MemoryCap: 5MB.
    • Scheduled Interval: Uncertain: A ResourceIntensiveTask will run when the phone meets the following conditions:
      • It’s connected to an external power source.
      • The battery is charged over 90%.
      • It has a WIFI connection or it’s connected through a PC.
      • The device screen is locked.
      • There is no active phone call.
    • Scheduled Duration: 10 minutes (If a RecourseInsensiveTask is run and the conditions of the devices change in a way that the ResourceIntensiveTask shouldn’t have been run, it’s terminated immediately).

    You can see by looking at the constraints above that there is no guarantee that a ResourceIntensiveTask will be run at all. The idea is that you use the PeriodicTask to do small updates, refresh an RSS feed for example. A typical scenario for a ResourceIntensiveTask would be an occasionally connected application, which stores data locally (perhaps in the new local database feature). If all the above conditions are met, the data could be synchronized with the server.

    Next to the constraints above, there are a couple of common constraints:

    • Each scheduled task will stop being scheduled after two weeks from the time it was first scheduled by using the Add() (later) method. Every time your main application is run, it can change this date to two weeks from the current time.
    • Scheduled tasks can’t use the API’s listed on the following page: http://msdn.microsoft.com/en-us/library/hh202962(v=VS.92).aspx.
    • Each application can schedule at most one PeriodicTask AND one ResourceIntensiveTask.
    • Tasks can only be scheduled the first time after a user initiated action from your main application. So you can’t make an application which schedules a background task as soon as it is installed.

    Scheduling a task

    Let’s take a look at the code needed to schedule a background task. The sample application contains one button. When this button is clicked it will schedule or prolong the already scheduled task. Here is the code behind:

       1: using System;

       2: using System.IO.IsolatedStorage;

       3: using System.Windows;

       4: using Microsoft.Phone.Controls;

       5: using Microsoft.Phone.Scheduler;

       6:  

       7: namespace MainApplication

       8: {

       9:     public partial class MainPage : PhoneApplicationPage

      10:     {

      11:         public MainPage()

      12:         {

      13:             InitializeComponent();

      14:         }

      15:  

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

      17:         {

      18:             base.OnNavigatedTo(e);

      19:             string minutes;

      20:             if (NavigationContext.QueryString.TryGetValue("minutes", out minutes))

      21:             {

      22:                 MessageBox.Show("The application was started by clicking a toast: " + minutes);

      23:             }

      24:         }

      25:  

      26:         private void HandleButtonClick(object sender, RoutedEventArgs e)

      27:         {

      28:             PeriodicTask myFirstTask;

      29:             myFirstTask = (PeriodicTask)ScheduledActionService.Find("MyFirstTask");

      30:             if (myFirstTask == null)

      31:             {

      32:                 //The first time this application is run....

      33:                 myFirstTask = new PeriodicTask("MyFirstTask");

      34:                 myFirstTask.Description = "Updates the tile with the current minutes and shows a toast";

      35:             }

      36:             else

      37:             {

      38:                 if (!myFirstTask.IsScheduled)

      39:                 {

      40:                     string lastResult;

      41:                     if (IsolatedStorageSettings.ApplicationSettings.TryGetValue<string>("taskResult", out lastResult))

      42:                     {

      43:                         if (lastResult == "Succes")

      44:                         {

      45:                             //User must have disabled it.

      46:                             MessageBox.Show("Please enable the background task in the settings menu and run this app again");

      47:                             ScheduledActionService.Remove(myFirstTask.Name);

      48:                             return;

      49:                         }

      50:                         else if (lastResult == "Faillure")

      51:                         {

      52:                             //Inspect isolated storage for more information and take appropriate action

      53:                         }

      54:                     }

      55:                 }

      56:                 ScheduledActionService.Remove(myFirstTask.Name);

      57:             }

      58:&nbsp; 

      59:             //Prolong the task or schedule a new one:

      60:             myFirstTask.ExpirationTime = DateTime.Now.AddDays(14);

      61:             try

      62:             {

      63:                 ScheduledActionService.Add(myFirstTask);

      64:             }

      65:             catch (InvalidOperationException)

      66:             {

      67:                 MessageBox.Show("Maximum amount of background tasks for your device might have been reached." +

      68:                     " Disable some tasks or enable this task on the settings menu and run this app again.");

      69:             }

      70:             catch (SchedulerServiceException)

      71:             {

      72:                 MessageBox.Show("Something really bad happened. an unexpected error has occurred.");

      73:             }

      74:&nbsp; 

      75:         }

      76:     }

      77:&nbsp; 

      78: }

    The most interesting part begins on line 29. When the button is clicked I first check whether the task already is scheduled. This is necessary because an application can only schedule one PeriodicTask. On line 33, if the task doesn&rsquo;t exist, I create it. Setting the description on line 34 is mandatory for a PeriodicTask. This is the description the user sees when he views all the scheduled background tasks through the settings menu. If it does exist, I check whether the task is still being scheduled on line 38. A scheduled task can become unscheduled because of two reasons:

    • The task called the Abort() method, to indicate something went wrong.
    • The user disabled the background task through the settings menu. If this is the case, the user can only allow the application to restart it&rsquo;s tasks when the application is launched. The user can&rsquo;t enable a disabled background task from the settings menu.

    As we&rsquo;ll see later, the only way you can find out what has happened is through IsolatedStorage. My task writes a result to IsolatedStorage (“Success&rdquo; or “Faillure&rdquo;). If the last result is “Success&rdquo;” and the task isn&rsquo;t scheduled, it must mean that the user has disabled it. If this is the case, I notify the user and remove the task on line 47 so that it can be restarted. I would really have liked a property on the PeriodicTask class, which I can use to determine the reason a task isn&rsquo;t scheduled anymore. Next to that, a way to find out if the task has been enabled again by the user, is also very welcome.

    If the last result is “Faillure&rdquo; or the task is still scheduled, I remove the task on line 56 (more about why I remove the task while it&rsquo;s still scheduled in a moment). You can of course log error details to IsolatedStorage from your task and inspect them here. After the inspection has been done, I let the method continue. The code from line 60 will be executed whether a new task has been created or an existing task has been found (which has or hasn&rsquo;t been aborted). On line 60 I set the ExpirationTime to two weeks from now, this is the maximum. This also means that an existing task is prolonged. You can&rsquo;t just change the ExpirationTime for an already scheduled task, this is why I removed it on 56. Finally, on line 63 I submit my task to the ScheduledActionService through the add method. This will make sure that the task is scheduled. You have to catch the InvalidOperationException on line 65. This will occur when the maximum amount of background tasks has been reached for a device or when the user disabled the background task for this application. The SchedulerServiceException on line 70 must also be caught, as this means a serious internal error.

    Note that to create a ResourceIntensiveTask, I only have to replace “PeriodicTask&rdquo; in the code above with “ResourceIntensiveTask&rdquo;. The configuration of the task is completely the same.&nbsp;

    The SchedulerAgent

    By now you, the well respected reader must have noticed something obvious&hellip;&hellip; I still haven&rsquo;t shown you the code that actually get&rsquo;s executed when the task is run by the operating system. This is because that code is is contained in a whole different Visual Studio project. You add this project by using the new “Windows Phone Task Scheduler Agent&rdquo; project template:

    image

    You should add this project to the same solution as the main project and immediately add a reference from the main project to this project. After you created this project, it already contains one class. This class will contain the code that will be run by the operating system:

       1: using System;

       2: using System.IO.IsolatedStorage;

       3: using System.Linq;

       4: using Microsoft.Phone.Scheduler;

       5: using Microsoft.Phone.Shell;

       6:&nbsp; 

       7: namespace MyFirstAgent

       8: {

       9:     public class TaskScheduler : ScheduledTaskAgent

      10:     {

      11:&nbsp; 

      12:         /// <summary>

      13:         /// Agent that runs a scheduled task

      14:         /// </summary>

      15:         /// <param name="task">

      16:         /// The invoked task

      17:         /// </param>

      18:         /// <remarks>

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

      20:         /// </remarks>

      21:         protected override void OnInvoke(ScheduledTask task)

      22:         {

      23:&nbsp; 

      24:             try

      25:             {

      26:                 ShellTile mainTile = ShellTile.ActiveTiles.First();

      27:                 //Tile has been pinned. First tile is always the main tile

      28:                 StandardTileData data = new StandardTileData();

      29:                 data.Count = DateTime.Now.Minute;

      30:                 data.Title = "Periodic";

      31:                 data.BackTitle = "Periodic back";

      32:                 mainTile.Update(data);

      33:&nbsp; 

      34:                 ShellToast toast = new ShellToast();

      35:                 toast.Title = "Info";

      36:                 toast.Content = "Tile was modified! Tap here to open the app.";

      37:                 toast.NavigationUri = new Uri("/MainPage.xaml?minutes=" + data.Count, UriKind.Relative);

      38:                 toast.Show();

      39:&nbsp; 

      40:                 IsolatedStorageSettings.ApplicationSettings["taskResult"] = "Succes";

      41:                 NotifyComplete();

      42:             }

      43:             catch (Exception)

      44:             {

      45:                 //Unschedule this task....

      46:                 Abort();

      47:                 IsolatedStorageSettings.ApplicationSettings["taskResult"] = "Faillure";

      48:             }

      49:             finally

      50:             {

      51:                 IsolatedStorageSettings.ApplicationSettings.Save();

      52:             }

      53:         }

      54:&nbsp; 

      55:         /// <summary>

      56:         /// Called when the agent request is getting cancelled

      57:         /// </summary>

      58:         protected override void OnCancel()

      59:         {

      60:             base.OnCancel();

      61:&nbsp; 

      62:&nbsp; 

      63:         }

      64:     }

      65: }

    The most interesting method is the one on line 21. It&rsquo;s the OnInvoke&nbsp; method. This method is called by the OS every time your task is run. The only argument is a ScheduledTask. This argument contains the PeriodicTask object I scheduled in the main application. You really only need this argument if your application schedules both a PeriodicTask and a ResourceIntensiveTask, since then you&rsquo;ll need an “if(task is PeriodicTask)&rdquo; statement to determine what code should be executed. In this method I use a couple of new API&rsquo;s in Windows Phone 7.1:

    • Line 26: I retrieve the main application tile. The first one is always the main tile, even if the application is not pinned, you can still update it and the user will see the update as soon as he pins the application.
    • Line 28: I update the BackTitle. This also new in Windows Phone 7.1. Tiles have a back, and as soon as you update it, Windows Phone will flip the tile in the home screen periodically to show the back.
    • On line 32: I update the tile with new information.
    • Line 34: I create a toast object. This is a notification that is shown to the user.
    • Line 37: A toast can have an Uri. When the user taps the toast, your application is started and your application navigates to this Uri, including the query string parameters. This way you can open your application in the correct state. You can see on line 16 of the main application that I do actually use this information in the OnNavigatedTo method. This is hard in the emulator to test, since the background task is run as soon as it&rsquo;s added to the ScheduledActionService. When it&rsquo;s run, my main application is still active and toast&rsquo;s won&rsquo;t be shown. So you&rsquo;ll have to close the application and wait for 30 minutes. After 30 minutes the PeriodicTask will be run again.
    • Line 43: I&rsquo;ve wrapped all code in a try..catch block. If an Exception occurs I call the Abort method. This let&rsquo;s Windows Phone know that the task should not be run again until I reschedule it from my main application. If everything went well, I call the NotifyComplete method on line 41. This let&rsquo;s Windows Phone know that the task can be safely run again.

    Conclusion

    Wow! Multi tasking in Windows Phone is a real cool feature to have. The ones explained above aren&rsquo;t the only ways to do some kind of multi tasking. In Windows Phone 7.1 there are also:

    • Scheduled Tile Updates.
    • Background Transfers.
    • Alarms.
    • Reminders.

    And they all are really not that difficult to understand and program. Working in the emulator to test a PeriodicTask is a bit of a pain. As soon as I use the Add method to schedule a task, Visual Studio loses the debug connection, because the debugger attaches itself to the background task. Next to that, the scheduled task is invoked immediately while my application is still active, so you won&rsquo;t see any toasts. To see toasts, you&rsquo;ll have to wait thirty minutes for the PeriodicTask to be run again. It would be nice for the future that we can configure the interval in which PeriodicTasks are run in the emulator. This would simplify testing. Just for completeness, here is a screenshot which shows the background task in the settings menu, under “Applications&rdquo; in Windows Phone 7.1:

    image

    You can see the description coming from my&nbsp;code in the last sentence in the screenshot above. The coming weeks I will be experimenting a lot more with Windows Phone 7.1, so if you find this interesting, keep an eye on this blog! You can find a working example here.

    Share this

Alex van Beek

View profile

IT Training at Info Support

Which training fits you?

Consultancy

Consultancy

Related blogs

  • Video Conferencing en OBS Studio koppelen: online prese…

    Video Conferencing en OBS Studio koppelen: online prese… Maaike Brouwer - 2 years ago

  • Verantwoordelijkheid pakken in jouw eigen persoonlijke …

    Verantwoordelijkheid pakken in jouw eigen persoonlijke … Stephan Versteegh - 2 years ago

  • Tips voor als je gaat afstuderen

    Tips voor als je gaat afstuderen Bart Renders - 3 years ago

Data Discovery Channel

  • Explainable AI - Break open the blackbox

  • Toekomstvaste microservice data architecturen

  • Modern Data Platform

Nieuwsbrief

* verplichte velden

Contact

  • Head office NL
  • Kruisboog 42
  • 3905 TG Veenendaal
  • T +31 318 552020
  • Call
  • Mail
  • Directions
  • Head office BE
  • Generaal De Wittelaan 17
  • bus 30 2800 Mechelen
  • T +32 15 286370
  • Call
  • Mail
  • Directions

Follow us

  • Twitter
  • Facebook
  • Linkedin
  • Youtube

Newsletter

Sign in

Extra

  • Media Library
  • Disclaimer
  • Algemene voorwaarden
  • ISHBS Webmail
  • Extranet
Beheer cookie toestemming
Deze website maakt gebruik van Functionele en Analytische cookies voor website optimalisatie en statistieken.
Functioneel Always active
De technische opslag of toegang is strikt noodzakelijk voor het legitieme doel het gebruik mogelijk te maken van een specifieke dienst waarom de abonnee of gebruiker uitdrukkelijk heeft gevraagd, of met als enig doel de uitvoering van de transmissie van een communicatie over een elektronisch communicatienetwerk.
Voorkeuren
De technische opslag of toegang is noodzakelijk voor het legitieme doel voorkeuren op te slaan die niet door de abonnee of gebruiker zijn aangevraagd.
Statistieken
De technische opslag of toegang die uitsluitend voor statistische doeleinden wordt gebruikt. De technische opslag of toegang die uitsluitend wordt gebruikt voor anonieme statistische doeleinden. Zonder dagvaarding, vrijwillige naleving door uw Internet Service Provider, of aanvullende gegevens van een derde partij, kan informatie die alleen voor dit doel wordt opgeslagen of opgehaald gewoonlijk niet worden gebruikt om je te identificeren.
Marketing
De technische opslag of toegang is nodig om gebruikersprofielen op te stellen voor het verzenden van reclame, of om de gebruiker op een website of over verschillende websites te volgen voor soortgelijke marketingdoeleinden.
Manage options Manage services Manage vendors Read more about these purposes
Voorkeuren
{title} {title} {title}