Saving State in a Suspending Metro Style App
The lifecycle of Metro style apps requires them to save their state when they are being suspended by the OS to prevent the potential loss of their state if they are restarted instead of resumed because they were inactive for two long.
The basic pattern of doing this is pretty simple. When the app is being suspended an event is raised by its Application
class. The application state can be saved inside the event handler attached to it:
sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
// do your work here
}
}
By inspecting the SuspendingEventArgs
passed to the handler you can see there's a deadline for completing the operation. The following snippet can be used to see how much time you actually have available:
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
Debug.WriteLine(e.SuspendingOperation.Deadline - DateTime.Now);
}
The output will constantly be approximately 5 seconds. That's the amount of time the OS gives the application to save its state before it forcibly stops the process. If you try running the following piece of code you might be in for a surprise, though:
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
await Task.Delay(1000);
Debug.WriteLine("Done");
}
There will be no output in this case. It turns out that if you want to take advantage of all the time available, you need to tell that to the OS otherwise it will stop you well before the time runs out. There's only a minor modification of the code above required:
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
try
{
await Task.Delay(1000);
Debug.WriteLine("Done");
}
finally
{
deferral.Complete();
}
}
Of course, you still need to be done before reaching the deadline, otherwise the OS will step in anyway.