WP7 Gotcha: Showing a Launcher or Chooser will crash while Navigating


Applies To: Silverlight & XNA (anyone using Launchers / Choosers)

Quick Bits

Always wrap [some launcher object].Show() with a try/catch block which catches InvalidOperationException, since running Show() while navigating (for example, if the user clicks your button multiple times quickly in succession) will cause this Exception to be thrown.

The Setup

You have a button that says “Purchase Me” which launches the Marketplace or one that says “Send Feedback” which launches Outlook to send an email. For example:

EmailComposeTask emailComposeTask = new EmailComposeTask();
emailComposeTask.To = "feedback@awesomeapps.contoso.com";
emailComposeTask.Subject = "Feedback for AwesomeApp";
emailComposeTask.Show();

The Sting

The user hits the button multiple times, quickly. The app crashes.

The Cause

If you debug this you’ll find that you can’t reproduce this behaviour on the Emulator (at least, I couldn’t) but that it reproduces pretty consistently on the phone. 

On the phone you’ll get an InvalidOperationException with the following message:

Navigation is not allowed when the task is not in the foreground. Error: -2147220989

The Solution

There are a couple of solutions – you could remember your state, so that if you clicked the button once and haven’t navigated back yet then you just don’t call Show(). Alternatively you could check if you were currently Navigating, and not call Show(). I personally prefer to wrap the statement in a try/catch block since it’s the easiest to have to worry about and the cost for the try/catch block is minimal (performance wise).

 

Comments (2)

  1. Kaushik Dev says:

    How can we check if there is a navigation in progress?

  2. orena says:

    There are a couple of ways that you can check if you are navigating:

    1. Compare NavigationService.CurrentSource and NavigationService.Source (if they're not the same then you are navigating)

    2. Set a state variable in the Navigating event handler and then clear it in Navigate(), NavigationStopped() and NavigationFailed().

    For more info on the NavigationService class see: http://msdn.microsoft.com/en-us/library/system.windows.navigation.navigationservice.aspx