What You Need To Know About Suspend and Resume in WinRT


Summary : While your Windows Store App runs, an end user can move their attention to another app which sends your app to the background. What should your app do in these circumstances? Luckily for us, Christophe Nasarre, Microsoft Premier Field Engineer, walks us through all the details, both in video form and in the post below. Enjoy!

For your convenience, here’s the video timeline (note that it will launch a new browser window):

[0:53] Process Lifecycle Walkthrough

[2:41] Task Manager and Suspension/Resume

[4:34] How to handle Suspending event and Deferral explanation

[8:16] How to immediately detect an App is leaving the screen

[10:49] How to figure out how long an App was suspended

[14:35] How to debug Suspend and Resume event handlers


Windows 8 provides a Process Lifecycle Management specific to the Windows Store Apps. In order to avoid problems, you need to understand how your App behaves according to certain user actions and how to react in your code.

High level view of an App lifecycle

We have seen in a previous post that a Windows Store App can be activated in many different ways: when the user taps on a tile in the Start screen, when a Search query is started or if the application is selected as a Share target.

While your app runs, the end user can move their attention to another app which sends your app to the background. In that case, after 10 seconds, Windows notifies your app via the Suspending event that its threads won’t be scheduled in 5 seconds. If the user switches back to your app, it will be woken-up by Windows and a Resuming event will be received. Note that while your app is suspended, Windows can decide to terminate it due to memory pressure from other applications. In that case, your app won’t be notified of this termination because it is suspended. However, the arguments sent to the app the next time it is activated provides the necessary details to figure out that it was terminated.

App Status

Suspension details

The Windows Task Manager allows you detect apps that are suspended. When you click the first Processes tab, you should see a Status column.

Windows Task Manager

By default, you won’t see the Suspended state there: you need to go to the View menu and select the Show suspended status of the Status value element

go to the View menu and select the Show suspended status

In the application class of your project, Visual Studio generated for you the code that registers the OnSuspending event handler with the Suspending event. The SuspendingEventArgs SuspensionOperation object received by this handler provides the time in the future after which Windows will terminate your app, regardless of whether you have finished saving your state! This Deadline property is readonly: it is just a hint for you.

SuspensionOperation object

The other member, the GetDeferral method, lets you retrieve a SuspendingDeferral object. You will find this notion of deferral in a lot of places with WinRT, because this is the basis of asynchronously handling an event.

Let’s go back to the Suspending event example. When you app returns from the OnSuspending event handler, Windows will freeze its threads. However, since most I/O operations are asynchronous in WinRT, the method will return at the first await construct in your code (SuspensionManager.SaveAsync in our code) while and maybe before your code is rushing to save its state!

So we have to find a way to tell Windows that it needs to wait until we are done before freezing our threads. This is the role of a deferral: when Windows creates a deferral, it postpones the execution of its code (here the code responsible for freezing our threads) until the method Complete of this deferral gets called. So, you perform whatever work is necessary to get you into a state from which you can comfortably resume (either seamlessly, or from a re-launch), then call the deferral object’s Complete method.

If you don’t call this method before the SuspendingOperation.Deadline expires, a timeout occurs and Windows guesses that something bad happened to your app… and, instead of being suspended, it will be terminated.

Sometimes, you might need to be immediately notified when your app switches to the background, in which case, you cannot rely on the Suspending event because it will be triggered 10 seconds after another app fills the screen. In the case of a game, this is not acceptable: you need to pause it as soon as the user stops being in front of the gaming surface. In that case, you can register a handler for the VisibilityChanged event of the app window. In the code generated by Visual Studio, a Frame instance is set as the app window:

// Place the frame in the current Window

Window.Current.Content = rootFrame;

After the Content property has been set, you register a method

Window.Current.VisibilityChanged += OnVisibilityChanged;

This handler will be called when your app is moved to the background, but also to the foreground: you detect which scenario by checking the Visible property of the received VisibilityChangedEventArgs

VisibilityChangedEventArgs

How to figure out how long your app was suspended

Unlike the Suspending event, the handler for the Resuming event does not receive any information.

the handler for the Resuming event

If you need to know the elapsed time since the suspension of your app, you have to compute it yourself. A simple solution is to keep track of the suspension time in the app settings from the Suspending event handler:

ApplicationData.Current.LocalSettings.Values["SuspensionTime"] =

    DateTimeOffset.Now;

 

and compare it with the current time in the Resuming event handler:

TimeSpan elapse = DateTimeOffset.Now -

    (DateTimeOffset)ApplicationData.Current.LocalSettings.Values["SuspensionTime"];

Simple isn’t it?

How to debug process lifecycle events

If you want to debug the code from the previous sections by setting a breakpoint in each handler and hitting F5 to start the debugger in Visual Studio, you will wait forever for these to trigger, even though your app switches back and forth to the screen!

The reason is simple: while an app is being debugged, Windows will not suspend it. If all threads were frozen, the debugger would not be able to interact with the application once suspended. Therefore, you need to use some special commands within Visual Studio to manually simulate these events. They are available from the Suspend item on the toolbar:

pecial commands within Visual Studio to manually simulate events

If you don’t see these commands in Visual Studio, right-click a toolbar and make sure the “Debug Location” group is selected:

make sure the “Debug Location” group is selected

Resources