Con l'avvento di Windows Phone 7.1, Microsoft ha introdotto alcune nuove caratteristiche per colmare la mancanza del multitasking della versione precedente. Per limitare il consumo della batteria e salvaguardare l'utente, solo un'applicazione può essere attiva in foreground e sebbene questo limite sia ancora presente, è possibile sfruttare i background agent per soddisfare la maggior parte delle esigenze che una applicazione possa avere.
Un background agent dal punto di vista dell'utente è un'attività che una applicazione può programmare di eseguire anche se l'applicazione non è attiva. Nelle impostazioni esiste un riquadro apposito di nome "attività in background", che permette di monitorarle e disattivarle. Dal punto di vista dello sviluppatore, i background agent sono classi che ereditano dalla classe ScheduledTaskAgent e implementano il metodo OnInvoke, per inserire la logica da eseguire. Vengono eseguiti in un processo diverso da quello dell'applicazione che lo detiene e potrebbero essere eseguiti contemporaneamente ad essa.
In Visual Studio 2010 è possibile creare un nuovo progetto di tipo "Windows Phone Scheduled Task Agent" che già crea una classe e il codice base. Una volta implementato è necessario referenziare tale progetto nell'applicazione Windows Phone che necessita del task. Questo fa sì che automaticamente il file WMAppManifest.xml venga modificato inserendo un tag BackgroundServiceAgent, fondamentale per l'individuazione della classe da istanziare ed eseguire.
Nello script si propone la creazione di un task che aggiorni la tile ciclando su un set di webcam da mostrare. Si procede quindi con la creazione del progetto e l'implementazione della classe, come nello snippet seguente.
public class ScheduledAgent : ScheduledTaskAgent { protected override void OnInvoke(ScheduledTask task) { // Recupero la tile associata all'applicazione ShellTile tile = ShellTile.ActiveTiles.First(); // Recupero l'ultimo indice dell'array utilizzato come immagine webcam int index; if (IsolatedStorageSettings.ApplicationSettings.TryGetValue("index", out index)) { index++; if (index >= images.Length) index = 0; } // Aggiorno la tile StandardTileData data = new StandardTileData { Title = images[index][0], BackgroundImage = new Uri(images[index][1]), BackBackgroundImage = new Uri(images[index][1]), BackContent = "Aggiornato alle " + DateTime.Now.ToShortTimeString(), }; tile.Update(data); // Salvo l'indice della webcam utilizzata IsolatedStorageSettings.ApplicationSettings["index"] = index; IsolatedStorageSettings.ApplicationSettings.Save(); NotifyComplete(); } private string[][] images = new[] { new[] {"Via Veneto", "http://images.webcams.travel/webcam/1267635323.jpg"}, new[] {"Raccordo anulare", "http://get.edidomus.it/vp/cam27/image.jpg"} }; }
Nel codice precedente si ottiene un riferimento alla tile dell'applicazione, che è sempre presente, anche se non pinnata. Si recupera dai settings l'indice dell'ultima webcam mostrata e si aggiorna la tile con la webcam successiva. Infine si salva l'indice e si notifica il sistema che il task è concluso mediante la chiamata NotifyComplete. E' possibile chiamare Abort se il task non è andato a buon fine, evitando che questo venga ripetuto, se previsto dalla programmazione.
Una volta sviluppato il task, nel punto che si ritiene opportuno (in questo caso non appena avviata l'app) è necessario programmare l'esecuzione del task. Per farlo occorre chiamare il metodo statico Add della classe ScheduledActionService passando la programmazione del task. Questa può essere di due tipi:
- PeriodicTask: task eseguiti ogni 30 minuti e per un massimo di 15 secondi, ideali per piccole attività;
- ResourceIntensiveTask: task eseguiti solo con wi-fi, con il device in ricarica e per un massimo di 10 minuti.
Un'applicazione può programmare entrambe i tipi di task (uno solo per tipo), ma l'implementazione è sempre la stessa, poiché essa può discriminare in base al tipo di task passato al metodo OnInvoke. Entrambe le tipologie di task scadono dopo 14 giorni dalla loro creazione, se non diversamente specificato e comunque non oltre quel termine. Questo limite è impostato per evitare che l'utente si dimentichi di attività in background dopo un lungo periodo di inattività. Per evitare che il task scada, è compito del programmatore rischedularla ogni qual volta l'utente avvia l'applicazione. Nel codice seguente quindi si verifica l'esistenza del task così da rimuoverlo e crearne uno nuovo.
const string taskName = "update"; // Cerco e rimuovo il task, se presente if (ScheduledActionService.Find(taskName) != null) ScheduledActionService.Remove(taskName); // Creo il task PeriodicTask task = new PeriodicTask(taskName); task.Description = "Aggiorna l'immagine della webcam"; try { // Schedulo il task ScheduledActionService.Add(task); } catch (InvalidOperationException exception) { // Controllo che il backgroun task non sia disattivato if (exception.Message.Contains("BNS Error: The action is disabled")) { MessageBox.Show("Impossibile aggiornare la webcam perché le attività in background sono disabilitate per questa applicazione"); } }
La gestione dell'eccezione è necessaria in quanto l'utente potrebbe dal pannello disattivare il task dell'applicazione, perciò si notifica l'utente di riattivare il task relativo. Il nome del task è ad uso interno, non va in conflitto con altre applicazioni e non riguarda il nome della classe del task.
A questo punto è possibile avviare l'applicazione e osservarne la tile.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Limitare le richieste lato server con l'interactive routing di Blazor 8
Sostituire la GitHub Action di login su private registry
Testare l'invio dei messaggi con Event Hubs Data Explorer
Migliorare la scalabilità delle Azure Function con il Flex Consumption
Creare una libreria CSS universale: Cards
Utilizzare gRPC su App Service di Azure
Modificare i metadati nell'head dell'HTML di una Blazor Web App
Sfruttare gli embedding e la ricerca vettoriale con Azure SQL Database
Utilizzare politiche di resiliency con Azure Container App
Disabilitare automaticamente un workflow di GitHub (parte 2)
Referenziare un @layer più alto in CSS
Ottimizzare la latenza in Blazor 8 tramite InteractiveAuto render mode
I più letti di oggi
- Effettuare il download di un file via FTP con la libreria FluentFTP di .NET
- Debug di app .NET tramite snapshot con Application Insight
- Utilizzare le Fullscreen API di HTML5 in IE11
- Proteggere l'accesso ad una Azure Web e API App tramite Google
- Utilizzare .NET Core con le Azure Function
- Effettuare il redirect da HTTP a HTTPS con la Azure CDN
- Creare un package MTS con uno script ASP
- Autenticazione con Minimal API di ASP.NET Core 6
- Routing HTTP con i proxy delle Azure Function
- Convidere una share di rete tra VM di Azure