31 Days of Windows Phone | Day #14: Tombstoning (Multi-tasking)

This post is Day #14 in a series called the 31 Days of Windows Phone.

Yesterday, we talked about using Location data to give our applications a more custom, in-the-know kind of feel.  Today, I’m writing on perhaps the most controversial topic available for Windows Phone 7: multitasking.

There’s been plenty of articles written about where Windows Phone 7 will struggle, and #1 at the top of that list is always “Lacks multi-tasking.”

Windows Phone 7 Does Multitasking

Yes.  I said it.  And I said it because it’s true.  A Windows Phone is absolutely a multi-tasking device.  I can listen to music while playing a game, or receive email while I’m surfing the web.  Where the misinformation appears is when we, as developers of apps for the platform, discover that we can’t build apps that run in the background.

In the many months that I have been working with Windows Phone 7, I have only been able to come up with two really compelling reasons to need my application to run in the background on my phone.

  1. My app plays music.  Like Pandora.  I will completely concede that this needs to be able to be done in the background.  The user will definitely notice if the music stops playing.
  2. My app needs data from the device’s sensors.  Like GPS.  If my app’s not running, I can’t tell you that you’ve run the 4 miles you wanted to run.

Outside of those two examples, however, I haven’t been presented with another situation in which having my app run in the background is necessary.  (For those of you writing apps that DO fall into one of those categories, you can appeal to the “powers that be” for access to a “super API” that DOES allow background processing.  I’ll warn you now though…you’re going to have to have a pretty compelling reason to get access to that.)

Before you say “but what about receiving updates from my web service?  Don’t I need to be running to get those?” my answer is NO, no you don’t.  There’s a great mechanism called Push Notification services that I will cover on Day #19 that solves this problem in a very elegant way.

For the rest of us, they’ve given us a great mechanism called “tombstoning” that allows us to pretend as if our application was always running, even though our process was killed.  Here’s a quick diagram of how it works:

tombstoninglifecycle

As you can see from the illustration above, there are deactivation and reactivation events that we can leverage when a user enters and exits our application.  By using these events, we can make it appear to our user as if our application never stopped running.  When we add in Isolated Storage (Day #15), and Push Notifications (Day #19), this becomes an incredibly powerful story.

Pretending to Multitask

There are four built-in methods in your App.xaml.cs file (for more information about the structure of your project files, check out Day #1).  Here’s a quick look at their default state, with the default comments inline.

// Code to execute when the application is launching (eg, from Start)
// This code will not execute when the application is reactivated
private void Application_Launching(object sender, LaunchingEventArgs e)
{
}

// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
}

// Code to execute when the application is deactivated (sent to background)
// This code will not execute when the application is closing
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
}

// Code to execute when the application is closing (eg, user hit Back)
// This code will not execute when the application is deactivated
private void Application_Closing(object sender, ClosingEventArgs e)
{
}

The “Launching” and “Closing” methods can be used in the traditional cases: starting and exiting the app through traditional methods (leaving with Back button, for example, or starting the app from the App List).  The Activated and Deactivated methods are for those non-traditional entrances and exits.  For example, using the Back button to go back to our application.  Or leaving our app because the user answered a phone call.  Those are non-traditional.  I recommend testing these cases heavily, but those should be solid guidelines to start with.

You are supposed to use these methods to save your state when a user exits your application, and then refresh that state when they return, thus creating the illusion that they never left.  The reason that we do this is pretty simple:

  1. Most users don’t realize that when they leave an application, it’s still eating system resources and battery life in the background. (If you’re reading this article, you’re NOT most users.)
  2. Most applications don’t NEED to run in the background.  There are better ways to use the device’s resources.

Saving Your State on Deactivation

The first thing we’re going to want to do when the user exits is save their information.  In my example application, we’re going to build a timer that appears to be running, even when it isn’t.  If you want to see all of the code, flip down to the bottom of this article, and look for the “Download the Code” section.  I’m only going to show the portions of the code relevant to tombstoning, but the entire application is available down there for you to play with.

To save data, I’m going to use the PhoneApplicationService.  I’m going to cover Isolated Storage tomorrow (Day #15), a more persistent way to save your data.  In my example, I want to know what time you exited my application, so that I can figure out the difference between when you exited and when you arrive the next time.

private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
	PhoneApplicationService.Current.State["LeftTime"] = DateTime.Now;
}

In my application, I also have an OnNavigatedTo event that fires when I load that page.  If my “LeftTime” value exists, then I use that, otherwise, I assume you are starting the application for the first time.

Restoring Your State on Reactivation

In this example, I restore my values from the ones that I saved when I exited.

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
	base.OnNavigatedTo(e);
	if (PhoneApplicationService.Current.State.ContainsKey("LeftTime"))
	{
		DateTime deactivated = (DateTime)PhoneApplicationService.Current.State["LeftTime"];
		secondsSinceStart = (int)(DateTime.Now - deactivated).TotalSeconds + (int)PhoneApplicationService.Current.State["ElapsedTime"];
		writeTime();
		writeDate();
		timer.Start();
	}
	else secondsSinceStart = 0;
}

By using this method, I am able to keep a continuous timer, even when the user leaves my application.  If you were to ask any user, they would tell you that the application is always running.  The only indication they’ll get will be a quick glance at a “Resuming” screen that only shows up if your application loads slowly.  I actually had to force my app to pause so that I could take the following screenshot:

resuming

So that’s the basic story behind tombstoning.  Save your state on the way out, and restore it on the way back in.  Your users will never know the difference, and you’ll give them better battery life, performance, and user experience.

Download the Code

A more complicated example of the code I showed above, my timer runs infinitely (even in the background).  Press the Start button on the emulator to exit, and use the Back button to return.  There’s also a TextBox you can enter text into, and it will save it when you exit.

download

11 thoughts on “31 Days of Windows Phone | Day #14: Tombstoning (Multi-tasking)

  1. Great information and just what I needed for my app. Short, clear and useful.

  2. Really? Only music and sensors? Only those two scenarios are valid for app-level multitasking?

    What if you need to refresh data in the background that is a large dataset that the user would not want to otherwise wait for? An example would be an RSS reader with lots of feeds. The user has to sit there while the whole thing refreshes for them. It can't happen in the background and be ready when the user focuses to the app.

    Or how about an application that has a long interval timer? For example, a cooking timer. The user may want to browse the web while waiting for the eggs to be hard boiled, but your timer is tombstoned and can't tell the user unless it has focus. What's that? Push notifications you say? Excellent idea… except that push notifications are not garaunteed delivery and are not time critical and can be delayed. And really… a web service is needed for a long interval timer? Talk about overkill.

    Or how about an app that enhances the user experience. For example, an app that looks at phone counter attributes (missed calls, SMS total, etc.) and performs an action based on state change. Let's say that there is an app that looks for SMS messages that are unread for over, say, an hour and it is set to send a canned reply like "sorry I'm busy so I haven't read your SMS yet, but I will soon." Impossible under WP7.

    I can think of dozens more scenarios in the same vein. Android and classic Windows Mobile can handle all of the above scenarios with ease.

  3. You are doing a great job here!!!
    Does with the new updates WP7 suport muttitasking ? Or this is going to be available only with the release of Mango version? Thanks!

  4. Can you edit your images?
    Some images are not available now.
    Thanks.

  5. Pingback: 31 Tage Mango | Tag #22: App Connect | leitning.de

  6. Pingback: Día 22: App Connect | La Liga Silverlight

  7. Hi jeffblankenburg,
    I , in my App downloading some xml in background. and I need to do it like if my app is deactivated or goes to background, I still want to continue downloading should I rewrite the code for background downloading in App_deactivated event handler.?

  8. Hi Jeff,

    Great work by providing all these articles to newbies like us, who are keenly interested in developing for WP7 and Windows 8 soon.

    The 2 scenarios you told us, which you thought would need multi-tasking. I scenario came into my mind as well. What if we need to build an utility app which leverages the WP7 OS, to work like an alarm clock. Now to wake us on time, this app would need to run in the background?

    I hope it makes sense?

  9. Hello,Jeff dowland link is broken and I can’t see any images.Thanks

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 )

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