WP7: Activating before Deactivated, a problem of Tombstoning

Tombstoning is the process that you save your app’s “state” to, usually Isolated Storage when the user leaves the app, so that your app can reload the state when it is been reactivated via the Back button.

Before going into the problem, you should have a good understanding on this concept. Shawn Wildermuth has a very good walk through of tombstoning and James Ashley also talked about why deactivating the application is not the same as tombstoning.

Assuming you save your app state using the Application_Deactivated event handler, there should be no problem at all, except this boundary case: what if the app is re-activated even before the Application_Deactivated handler finishes it’s execution?

It’s quite simple to produce this situation. You can:

  • either put a break point in debug mode in the Application_Deactivated event handler, then press Home then Back buttons, then F5 your app to resume it;
  • or simply put Thread.Sleep(5000) in the event handler and press Home then Back buttons within 5 seconds.

If you observe this process carefully in debug mode, the behavior is quite interesting here: the Application_Activated event handler will still be invoked after Application_Deactivated but your app instance is not destroyed and recreated. This means when the app is reactivated, none of the constructor of your objects will be called, as if there weren’t a deactivation at all. To put this in short: tombstoning is not needed in this case!

Having this in mind, we should carefully code our logic so that we don’t do unnecessary tombstoning operations that may cause unwanted side effects.

For example, if you were saving and loading your setting like this:

private ObservableCollection<string> _searchResults;
public ObservableCollection<string> SearchResults{
    get { return _searchResults; }
    set { _searchResults = value; RaisePropertyChanged("SearchResults"); }
}

private void Application_Activated(object sender, ActivatedEventArgs e)
{
    SearchResults = LoadSearchResultsFromIsoStore();
}

private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
    SaveSearchResultsToIsoStore(SearchResults);
}

The above code could trigger an unnecessary write and read of IsolatedStorage in our special case, and if SearchResults is large and bound to a UI list with complicated item template, there will be much more side effects then just performance hit for reloading it unnecessarily.

Unfortunately, it’s most likely that we won’t be able to avoid the potential redundant write to IsolatedStorage in Application_Deactivated, because there is no way that we can predict if the app will be reactivated too soon. But we can always be smart in Application_Activated. For example:

private void Application_Activated(object sender, ActivatedEventArgs e)
{
    if (SearchResults == null) SearchResults = LoadSearchResultsFromIsoStore();
}

In this example, we can easily know that if the app has been destroyed or not by checking whether SearchResults is null. If the app instance was never recreated, then SearchResults would still be pointing to something other than null. Depends on how you organise your tombstoning logic, there could be a thousand different ways to be smart here. Just keep this case in mind when you code.

Advertisements

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