Come abbiamo più volte accennato, una delle novità più significative introdotte da Windows RT riguarda il "ciclo di vita" di un'applicazione. Non solo non è possibile eseguire contemporaneamente più di un'istanza della stessa Windows Store app, ma quando l'utente lascia l'applicazione corrente per attivarne un'altra, la prima viene automaticamente sospesa dal runtime, per poi essere ripristinata nello stesso stato in cui l'avevamo lasciata qualora l'utente la riattivi (e sempre che, nel frattempo, non sia stata terminata dal sistema operativo, ma su questo aspetto torneremo più nel dettaglio in un prossimo articolo).
L'idea che sta dietro queste scelte è quella di migliorare il grado di "responsiveness" del sistema anche nel caso (piuttosto comune) in cui l'utente apra più applicazioni. In questo modo, infatti, solo l'applicazione correntemente utilizzata dall'utente "ruba" tempo processore, mentre tutte le altre applicazioni Windows Store vengono poste dal runtime di Windows in uno stato di sospensione. In questo stato, la RAM occupata dall'applicazione viene come "congelata" (e ripristinata in seguito alla riattivazione, come se nulla fosse successo), mentre CPU, network e dischi non vengono utilizzati per tutto il tempo della sospensione.
Nell'immagine seguente, l'applicazione nativa Mail a seguito della sua sospensione da parte di Windows RT:
Nel momento in cui l'utente torna sull'applicazione sospesa, questa viene immediatamente ripristinata dal sistema operativo nello stesso identico stato in cui si trovava prima della sospensione: il sistema infatti "scongela" la RAM riportando l'applicazione in foreground, senza che sia necessario ripassare dall'evento di attivazione e conseguente re-inizializzazione dell'applicazione ad opera del metodo OnLaunched.
L'utente ha la sensazione che l'applicazione non abbia mai cessato effettivamente di funzionare in background, anche se in realtà adesso sappiamo che l'applicazione è stata semplicemente congelata per tutta la durata della sospensione, con conseguente risparmio di risorse del sistema operativo.
Guai però a pensare che questo meccanismo ci esoneri dal preoccuparci di salvare lo stato dell'applicazione (ad esempio, i campi di un form parzialmente riempiti dall'utente prima della sospensione). Se è vero infatti che durante la sospensione nessuna informazione o dato viene perduto, è anche vero che, se in un certo momento il sistema operativo ha bisogno di liberare risorse, le applicazioni in stato di sospensione saranno terminate senza alcuna notifica da parte del runtime.
In questo sta uno degli aspetti più innovativi di Windows RT, ed è importante comprenderne bene il funzionamento: tanto la sospensione, quanto la chiusura di un'applicazione sono gestiti direttamente dal sistema in modo automatico.
Quando la nostra applicazione viene messa in background dal sistema operativo a fronte della scelta dell'utente di passare ad un'altra applicazione, questa viene posta in stato di sospensione da Windows RT (trascorso un intervallo di tempo di tempo che è lo stesso runtime a determinare) inviando l'evento si sospensione alla nostra applicazione. Quando il sistema è "saturo" e ha bisogno di liberare risorse, è sempre Windows RT che termina la nostra applicazione, senza però darci alcun preavviso e senza che sia possibile "reagire" all'evento via codice.
Pertanto, se vogliamo salvare lo stato in cui si trovava l'utente prima di passare ad altre applicazioni, è nel momento della sospensione che dobbiamo prepararci, perché dopo di questo non avremo altre occasioni. Ciò chiarito, il "posto" dove prendere le misure necessarie in vista della sospensione è rappresentato dall'handler dell'evento Suspending che Windows RT solleva subito prima di iniziare le relative operazioni.
Per vedere in pratica il funzionamento di questo meccanismo, apriamo nuovamente l'applicazione sviluppata nella lezione precedente. Nel costruttore della classe App.xaml.cs
, che come ormai sappiamo costituire l'entry point della nostra applicazione, possiamo notare l'handler dell'evento di sospensione aggiunto di default dal template di Visual Studio 2012:
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending; // aggiungere l'handler
}
Quella che segue è invece l'implementazione di default dell'handler:
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
Avremo modo più avanti di tornare sul significato del codice di default (e in particolare sul metodo GetDeferral
), per il momento limitiamoci a implementare un handler custom per l'evento di sospensione. Modifichiamo il costruttore della classe App.xaml.cs come segue :
public App()
{
this.InitializeComponent();
//this.Suspending += OnSuspending; // -- questa viene commentata
this.Suspending += AppSuspending; // al posto della precedente
}
Implementiamo adesso il nostro handler affinché mostri un MessageDialog che ci avverta che nostra applicazione è stata sospesa:
private void AppSuspending(object sender, SuspendingEventArgs e)
{
String message = "L'applicazione è stata sospesa";
var dia = new Windows.UI.Popups.MessageDialog(message, "DevLeap ALM Demo");
dia.ShowAsync();
}
Effettuiamo un deployment dell'applicazione e lanciamola. Dopo aver chiuso il MessageDialog iniziale del launch, poniamo l'applicazione in background (basterà aprire una qualunque altra applicazione Windows Store, come Mail o Internet Explorer) e attendere qualche secondo. Per sapere il momento effettiamo controlliamo il Task Manager per verificare quando verrà effettivamente sospesa da Windows RT.
Quando l'applicazione viene sospesa, non essendo più in foreground da qualche secondo, non potrà mostrare il dialog che abbiamo preparato da codice. Questo dialog verrà mostrato nel momento in cui la nostra applicazione tornerà in foreground. Riapriamola premendo ALT+TAB o cliccando sul relativo tile.
Il risultato della procedura è mostrato nella prossima immagine:
Da notare il fatto che, al momento del ripristino, non è apparso il MessageDialog iniziale, il che testimonia come l'applicazione non sia passata dal metodo OnLaunched (che, come si ricorderà, è invocato dal runtime al momento dell'attivazione dell'applicazione).
In alternativa, è possibile simulare lo stato di sospensione direttamente in Visual Studio 2012 senza dover attendere le decisioni del Windows Runtime. Semplicemente eseguendo l'applicazione con F5
e premendo il pulsante Suspend nella toolbar di Visual Studio denominata Debug Location (attivabile nel menu View). Una volta sospesa, cliccate su Resume per ripristinare l'applicazione.
Un altro aspetto di fondamentale importanza riguarda il tempo che intercorre tra la notifica, da parte di Windows RT, dell'avvio delle operazioni di sospensione e l'effettiva sospensione dell'applicazione stessa. Anche su questo punto Windows 8 opera una scelta piuttosto radicale: alla nostra applicazione vengono infatti concessi non più di 5 secondi per completare le operazioni di salvataggio dei dati per la sospensione; se al termine di questo intervallo di tempo le operazioni non sono concluse (perché, ad esempio, il servizio che usiamo per salvare i dati inseriti dall'utente impiega più del previsto a rispondere), Windows RT procede direttamente a terminare l'applicazione. Per toccare con mano questo comportamento, provate ad aggiungere questa banalissima riga di codice all'inizio del metodo AppSuspending in modo da determinare un ciclo infinito:
while (true);
Effettuate un nuovo deployment, lanciate l'applicazione, mettetela in background e osservate il Task Manager: pochi secondi dopo che il runtime ha posto l'applicazione in sospensione, questa scomparirà dall'elenco, segno inequivocabile che l'applicazione è stata terminata.
Se attivate nuovamente l'applicazione, nel primo MessageDialog dovreste trovare adesso l'indicazione "Previous State: Terminated" (tuttavia, come già notato, il sistema operativo impiega un tempo variabile per completare le relative operazioni, per cui non meravigliatevi di trovare "Previous State: NotRunning"; se volete essere sicuri di visualizzare lo stato corretto, potete usare il debugger di Visual Studio 2012 per eseguire l'applicazione e cliccare sul pulsante Suspend and shutdown per simulare la chiusura dell'applicazione).
Il Windows Runtime sospende una applicazione dopo qualche secondo da quando l'utente passa ad un'altra applicazione. La sospensione ci consente di salvare lo stato dell'applicazione e volendo i dati temporanei inseriti dall'utente per essere pronti ad una eventuale terminazione da parte del sistema operativo.
Il sistema operativo esegue un resume della applicazione quando l'utente torna sull'applicazione (il cui codice verrà analizzato nel prossimo articolo). Il sistema può però anche decidere di terminare le applicazioni in stato di sospensione se necessità di risorse.