Il multitasking in Mango: i background agents – Passiamo ai fatti

Print Content | More

Nel post precedente abbiamo visto la teoria necessaria per capire cosa sono e come funzionano i background agents. Ora è giunto il momento di passare alla pratica e realizzare un’applicazione che faccia uso di un agent.

Come prima cosa, dobbiamo creare due progetti di Visual Studio: se ricordate quanto detto nel post precedente, un background agent è una DLL separata dall’applicazione vera e propria. Creiamo perciò una nuova soluzione in Visual Studio e aggiungiamo due progetti: uno di tipo Windows Phone Application e l’altro di tipo Windows Task Scheduler Agent.

L’applicazione Windows Phone

Nell’applicazione Windows Phone andremo a creare il background agent e ad aggiungerlo allo scheduler di Windows Phone. Nel post precedente abbiamo visto come esistano due tipi di agents: entrambi si istanziano allo stesso modo ed espongono le stesse proprietà, l’unica differenza è il tipo di oggetto che andremo ad utilizzare.

Vediamo un esempio:

ScheduledAction action = ScheduledActionService.Find("TestAgent");
if (action != null)
    ScheduledActionService.Remove("TestAgent");

PeriodicTask task = new PeriodicTask("TestAgent")
                        {
                            Description = "Test task",
                            ExpirationTime = DateTime.Now.AddDays(7)
                        };

ScheduledActionService.Add(task);

Tutti i background task introdotti in Mango derivano da una classe base chiamata ScheduleAction, che rappresenta per l’appunto un generico servizio capace di girare in background. ScheduledActionService rappresenta invece lo scheduler di Windows Phone (lo abbiamo già visto quando abbiamo parlato di reminders e alarms), che si occupa di gestire tutti i task in background che sono stati introdotti in Mango. Ecco perciò che come prima cosa andiamo a controllare se nello scheduler è già presente un servizio con lo stesso nome e, in caso affermativo, lo rimuoviamo: se infatti cercassimo di aggiungere un task duplicato allo scheduler, otterremmo un’eccezione.

Dopodichè definiamo il nostro background agent: nell’esempio, si tratta di un periodic agent (che fa riferimento alla classe PeriodicTask). Se si fosse trattato di un resource intensive agent il codice sarebbe stato lo stesso, con la differenza che l’oggetto istanziato sarebbe stato di tipo ResourceIntensiveTask. Il task viene istanziato con un nome, una descrizione e una data di scadenza, passata la quale viene automaticamente eliminato da quelli schedulati.

Infne aggiungiamo il task nella coda dello scheduler, sfruttando il metodo Add esposto dal servizio ScheduledActionService.

Ci siamo: il nostro task è stato definito e ora Windows Phone lo prenderà in carico secondo le regole che abbiamo visto nel post precedente e in base al tipo di agent che abbiamo definito. Ora dobbiamo definire però che cosa farà effettivamente il nostro background agent.

Il background agent

Il progetto di tipo Windows Background Scheduler Agent che abbiamo creato all’inizio avrà già una classe definita al suo interno, di nome TaskScheduler, che possiamo rinominare a nostro piacimento. Questa classe rappresenta il nostro agent ed ha tre caratteristiche fondamentali:

  • Eredita dalla classe ScheduledTaskAgent
  • Implementa il metodo OnInvoke, che contiene il codice che viene eseguito quando il background agent viene lanciato.
  • Implementa il metodo opzionale OnCancel, che viene invocato nel momento in cui il tempo assegnato al nostro agent sta per scadere. Nel caso in cui le operazioni definite nel metodo OnInvoke non siano ancora concluse, possiamo usare questo metodo per gestire eventuali operazioni che vogliamo eseguire prima che questi venga definitivamente terminato.

Il cuore è il metodo OnInvoke, in cui possiamo inserire il codice che vogliamo, l’importante è che rispetti le condizioni spiegate nel post precedente a cui devono sottostare gli agents (ad esempio, nessuna interazione con la UI o utilizzo di librerie di XNA). Vediamo un semplice esempio in cui usiamo un background agent per mostrare una notifica di tipo toast:

public override void OnInvoke(ScheduledTask task)
{
    ShellToast toast = new ShellToast
                           {
                               Title = "Toast",
                               Content = "Test"
                           };
    toast.Show();
    NotifyComplete();
}

Il codice è semplice: creiamo una notifica di tipo toast, gli diamo un titolo e un testo fittizi e la mostriamo (torneremo in un prossimo post sulle notifiche push locali). L’unica cosa da notare è la chiamata al metodo NotifyComplete, che deve essere richiamato nel momento in cui il background agent ha terminato il suo compito. In questo modo, lo scheduler di Windows Phone è in grado di liberare le risorse utilizzate dall’agent il prima possibile.

Come collegare l’agent all’applicazione

Nell’applicazione abbiamo aggiunto un nuovo task allo scheduler, mentre nel background agent abbiamo definito le operazioni da eseguire. Come facciamo a collegare i due, per far si che l’applicazione sappia qual è il task che vogliamo utilizzare? Il tutto viene definito nel file di manifest, che già abbiamo visto in passato in quanto definisce tutte le funzionalità del device che vengono utilizzate dalla nostra applicazione (accesso ai sensori, utilizzo della rete, ecc.).

Ecco la sezione del manifest della nostra applicazione dove viene dichiarato il background agent:

<Tasks>
  <ExtendedTask Name="BackgroundTask">
    <BackgroundServiceAgent Specifier="ScheduledTaskAgent" Name="TestAgent" Source="TestAgent" Type="TestAgent.TaskScheduler" />
  </ExtendedTask>
</Tasks>

L’agent è identificato da:

  • Name: il nome dell’agent
  • Source: il nome della DLL che contiene l’agent (tipicamente coincide con il nome del progetto)
  • Type: il namespace completo (compreso del nome della classe) dell’agent all’interno della DLL

In realtà, aggiungere le informazioni sull’agent nel manifest è estremamente semplice, dato che ci penserà Visual Studio a fare tutto: quello che dovrete fare voi sarà semplicemente aggiungere una reference all’agent all’interno della vostra applicazione (tasto destro sul progetto, selezionate Add Reference e selezionate il progetto contenente l’agent che sarà disponibile nella sezione Projects).

Come effettuare il debug?

In Visual Studio esiste una toolbar che vi permette di vedere i processi in esecuzione, che assume una certa importanza nella nuova versione dei tool. Ora infatti sono due le tipologie di processi che Visual Studio si troverà a gestire: UI Task (l’applicazione vera e propria) e background task (il background agent). Quando lancerete il debugger di Visual Studio, se la vostra applicazione prevede un agent verranno deployati entrambi. Nel momento in cui uscirete dall’applicazione, noterete che il debugger non si staccherà; verrà infatti eseguito l’agent e, se avete messo un breakpoint all’interno del metodo OnInvoke, potrete fare debug step by step del vostro codice.

agents

In conclusione

Abbiamo visto una panoramica (spero esauriente) sui background agent: prossimamente parlerò anche di un tipo particolare di background agent, quello dedicato alla gestione dell’audio in background. Nel frattempo, potete fare esperimenti con il progetto di esempio che trovate in allegato. Buon download!


Windows Phone , Mango , Background agents , Microsoft , Multitasking

2 comments

Related Post

  1. #1 da Matteo Tumiati Friday June 2011 alle 01:40

    Ciao, sei stato molto chiaro ma volevo chiederti una cosa un po' più nello specifico.. Il metodo OnCancel quanto tempo prima viene chiamato? Viene stabilito direttamente dal sistema operativo in base alle esigenze oppure è un tempo fisso?

  2. #2 da Matteo Pagani Friday June 2011 alle 01:50

    Ciao Matteo,
    ho spulciato un pochino nella documentazione MSDN ma non ho trovato dettagli precisi.
    L'unica informazione a riguardo è che, una volta invocato il metodo OnCancel, le operazioni definite al suo interno hanno massimo 5 secondi di tempo per essere eseguite, altrimenti l'agent viene brutalmente terminato.

    Ciao!


(will not be published)
(es: http://www.mysite.com)