Sunday 29 March 2015

Most of my Windows 8 apps are broken. Yours probably are too.

Tonight, after a day of user testing an upcoming app, we ran into some crashes, and some undesirable behavior.

So, we set about trying to fix the problems.  So far so good.

One of the problems was the app needed to keep the display from timing out while running.

Enter DisplayRequest and it’s RequestActive and RequestRelease methods.  On a particular page in my app, I called RequestActive during OnNavigatedTo and RequestRelease during OnNavigatedFrom.

Unfortunately, we ran into trouble when we started playing with our suspend/resume handling.  They started throwing ArithmeticExceptions!

So, a quick check of the DisplayRequest Documentation shows some sample code with it catching exceptions.  As a result, I eventually decided to write a wrapper class to handle the outstanding requests, and follow he advice on that page.

  • Release all display requests when the app is suspended. If the display is still required to remain on, the app can create a new display request when it is reactivated.

To support this, we called RequestRelease for each time it had been requested active, and in the restore code, we call request active again.  Unfortunately that still didn’t work, as it turned out that OnNavigatedFrom was being called after we’d released everything in the Suspending call.  So, I went looking for trouble.

Usually when you look for trouble you can find it

Turns out, I wasn’t the only one with problems.

This discussion on the Suspension Manager points out the issue of things not being called in matching pairs.

And this advice about Saving and Restoring State in a Windows 8 XAML App shows that you only call SuspensionManager.RestoreAsync() in certain cases.  I expect that’s derived from the advice on this page about Application Lifecycle where they explicitly state “most apps don’t need to do anything when they are resumed”  The advice from Patterns and Practices is similarly broken.

And that combination is the cause of the bug.

Naturally, after 3 hours of research, I now no longer need my global class that manages the count of the number of DisplayRequest.ReleaseRequest and RequestActive calls I’ve made.

 

TL;DR

On a suspend your OnNavigatedFrom handler may be called, but on resume, OnNavigatedTo isn’t.  All sorts of paired handlers may not work as you expected.

You might want to look at OnNavigatingFrom instead but I’m still not convinced that’s correct either.