Suspension Manager

Nein es geht nicht um Frührente. der Lebenszyklus von Windows 8 METRO Anwendungen etwas eigenwillig. Kurz gesagt, kann man das Betriebssystem einen in den Hintergrund gelegte Anwendung aus dem Betriebssystem Sheduler entfernen. Der Modus nennt sich suspended.

image

warum und wieso dauert etwas länger zu erklären.  Relevant ist, was man aus Coding Sicht tun muss.

Eigentlich muss man gar nichts tun. Die Anwendung wird ja nicht geschlossen, insofern kommt sie in dem Status zurück wie man sie zuletzt gesehen hat. Eine Textbox beinhaltet noch immer den Text. Aber Windows 8 hat das rechteine Suspended APP komplett zu entfernen. Ich habe das zwar noch nie gesehen, aber  bei kommenden ARM Geräten mit wenig Arbeitsspeicher wird das wohl passieren.

Sämtliche Beispiele aus dem SDK enthalten eine Hilfsklasse die sich SuspensionManager nennt.Ich kopiere die aktuell in meine Projekte, auch wenn sie nicht optimal ist.

Module SuspensionManager
    Private sessionState_ As New Dictionary(Of String, Object)
    Private knownTypes_ As List(Of Type) = New List(Of Type)
    Private Const filename As String = "_sessionState.xml"

    ' Provides access to the currect session state
    Public ReadOnly Property SessionState As Dictionary(Of String, Object)
        Get
            Return sessionState_
        End Get
    End Property

    ' Allows custom types to be added to the list of types that can be serialized
    Public ReadOnly Property KnownTypes As List(Of Type)
        Get
            Return knownTypes_
        End Get
    End Property

    ' Save the current session state
    Public Async Function SaveAsync() As Task
        ' Get the output stream for the SessionState file.
        Dim file As StorageFile = 
Await ApplicationData.Current.LocalFolder.CreateFileAsync(filename,
CreationCollisionOption.ReplaceExisting) Dim raStream As IRandomAccessStream =
Await file.OpenAsync(FileAccessMode.ReadWrite) Using outStream As IOutputStream = raStream.GetOutputStreamAt(0) ' Serialize the Session State. Dim serializer As New
DataContractSerializer(GetType(Dictionary(Of String, Object))) serializer.WriteObject(outStream.AsStreamForWrite, sessionState_) Await outStream.FlushAsync End Using End Function ' Restore the saved sesison state Public Async Function RestoreAsync() As Task ' Get the input stream for the SessionState file. Try Dim file As StorageFile =
Await ApplicationData.Current.LocalFolder.GetFileAsync(filename) If file Is Nothing Then Exit Function End If Dim inStream As IInputStream = Await file.OpenSequentialReadAsync ' Deserialize the Session State. Dim serializer As New DataContractSerializer(GetType(Dictionary(Of String, Object))) sessionState_ = CType(serializer.ReadObject(inStream.AsStreamForRead),
Dictionary(Of String, Object)) Catch ex As Exception ' Restoring state is best-effort.
If it fails, the app will just come up with a new session. End Try End Function End Module

In der Applikation Klasse app.xaml.vb wird dann diese aufgerufen wenn die Anwendung schlafen geht oder wieder aufwacht.

Protected Async Sub OnSuspending(ByVal sender As Object, 
ByVal args As SuspendingEventArgs) Handles Me.Suspending Dim deferral As SuspendingDeferral = args.SuspendingOperation.GetDeferral Await SuspensionManager.SaveAsync deferral.Complete() End Sub Protected Overrides Async Sub OnLaunched(ByVal args As LaunchActivatedEventArgs) If args.PreviousExecutionState = ApplicationExecutionState.Terminated Then ' Do a synchronous restore Await SuspensionManager.RestoreAsync End If

Spannend ist der Part in dem man per Getdeferral WinRT bittet die Anwendung vom Suspending zu verschonen. Schließlich kann das speichern ja etwas länger dauern und damit wird der 5 Sekunden Zyklus unterbrochen.

Ob die Anwendung vom Suspended oder Terminated Modus kommt, spielt für das Restore der Settings natürlich eine Rolle.

Im eigentlichen VB.NET Programmcode wird auch der Suspensionmanager um einer Art Session wie in ASP.NET relevanten Infos abzulegen. So kann das ausgewählte Listenelement  wieder hergestellt werden.

If SuspensionManager.SessionState.ContainsKey("SelectedScenario") Then
            Dim selectedScenarioName As String = 
TryCast(SuspensionManager.SessionState("SelectedScenario"), String) startingScenario =
TryCast(Me.FindName(selectedScenarioName), ListBoxItem) End If

Kommentar schreiben