WinRT application model is completely different than the existing application models. The Metro style applications are meant to work differently with least user intervention on the apps. So the user for the Metro application does not need to close the application ever. The operating system takes care of memory constraint and suspend the application or even terminate the application when required. But the user will not be aware of the fact that the application has been unloaded from the memory, the application will still remain in the context, and when it is activated, the application is recreated and launched.
Thus if the application is in intermediate state when the application is relaunched after terminating, the application will look completely different than what the user has left of when launching some other application. So for a developer you should always auto store the data as well as the application state information when the application is being suspended. In this post, we will see where to store data when the application is automatically suspended by the WinRT environment.
Every application you create on WinRT Metro has a WinRT class called App (unlike wpf, its made of WinRT interfaces, but acts the same). This class has few events that needs to be trapped when the application gets suspended and turned back. Lets take a look at the code below :
public App() { InitializeComponent(); this.Suspending += new SuspendingEventHandler(App_Suspending); this.Resuming += new Windows.UI.Xaml.EventHandler(App_Resuming); } void App_Resuming(object sender, object e) { // Write code to update ui only for items that are outdated. // This is resume from suspended state, so it does not lose any data } async void App_Suspending(object sender, Windows.ApplicationModel.SuspendingEventArgs e) { // Write code to store data so that when the application is terminated the state can be recovered. // Allowed only 5 seconds to do the storage SuspendingDeferral deferral = e.SuspendingOperation.GetDeferral(); await ApplicationStateModel.SaveAllApplicationDataAsync(); await ApplicationStateModel.SaveSessionStateAsync(); deferral.Complete(); }
The code above defines two event handler for events Suspending and Resuming. Suspending is an event that occurs when the application gets suspended by the WinRT application. The block that runs Suspended code, has 5 seconds before the application turns off the application to store application state. The application state is necessary if the WinRT environment wants to terminate the application, so that when the user activates it needs to get the states.
We use here the Async and await contextual keywords to store ApplicationData and ApplicationState. We do this in sequence because ApplicationData stores unsaved data which are sensitive to the user and the State stores information on user state. We annotate the code using a SuspendingDeferral object. This is a ManualSetter object which tells the WinRT environment that the method has not finished execution and wait until either Complete is invoked or 5 seconds has been elapsed.
Resuming is generally not required often, but it is generally used to refresh the old data, if the application is being suspended for a long time.
On the other hand when the application gets terminated and relaunched again, you need to write code to retrieve the user application data and state from persistent storage and update the UI. To do this we use OnLaunched method on App class.
protected override void OnLaunched(LaunchActivatedEventArgs args) { this.LoadStates(args.PreviousExecutionState); Window.Current.Content = new MainPage(); Window.Current.Activate(); } private async void LoadStates(ApplicationExecutionState applicationExecutionState) { // Write code to determine what you need to do when application is eitner terminated or suspended switch (applicationExecutionState) { case ApplicationExecutionState.Suspended: // Will be called when application is launched from suspension break; case ApplicationExecutionState.Terminated: await ApplicationStateModel.RecoverStateAsync(); break; case ApplicationExecutionState.NotRunning: // This will occur when the appliction is launched for the first time break; } }
Each state holds its meaning. Generally we need to use PreviousExecutionState to determine what needs to be done with the application when the application gets relaunched.
If you run the application and look at the task manager you will see the application got suspended after an interval. But this will occur only when you are not in debugging mode. When you are in, it does not ever put the application in suspension. To deal with this situation and debug suspension, we have a special option in visual studio called Trigger Suspend and Trigger Resume from Debug menu.
As Visual studio disables the application suspension and termination when it is launched in debug mode, you do not have an option to test your Suspension code. In debug menu of Visual Studio although you have an option which lets you suspend your application, and hence if you put a breakpoint on the code, it will hit it.
BTW, you dont have the problem of 5 seconds to save Suspension in debug mode for your application.
I hope this comes handy.
Thank you for reading.