Redazione
a- a+

Silverlight: migliorare la performance delle applicazioni

Silverlight: migliorare la performance delle applicazioni

I computer che contengono un solo processore sono capaci dieseguire solo un singolo task per volta. In questo caso, comefa un sistema operativo elaborato come Windows ad eseguireoperazioni concorrenti così come ospitare in memoriapiù applicazioni simultaneamente, ognuna delle qualisvolge un proprio compito? La risposta è che ilsistema operativo gestisce ciclicamente e molto efficacementeil tempo che il processore assegna ad ogni singolo processo,permettendo ad ognuno di loro di essere eseguito a turno perun brevissimo periodo di tempo. Questo dàl'illusione che il tutto avvenga simultaneamente econtemporaneamente.

Ogni processo tipicamente tenta di eseguire un singolo taskper cui ciascun processo viene assegnato ad un singolothread di esecuzione (una porzione del tempo delprocessore) per completare il proprio task. La maggior partedel codice viene scritto per eseguire un singolo task allavolta e per completarlo prima di passare ad un altro. Questotipo di processazione viene definitasincrona. Nella maggior parte degli scenari,l'esecuzione sincrona del codice è piuttostoveloce e sufficiente per i task più comuni. Inoltremolte volte, alcuni task dipendono dal completamento di untask precedente, ad esempio quando si interroga un database,la query non può esser eseguita fintanto che non sistabilisce una connessione con il database.

Ad ogni modo esistono alcuni task eseguiti nel codice che nondipendono da altri task per essere completati. Quando i taskpossono essere processati indipendentemente, si incrementa laperformance se il task può essere eseguitoparallelamente ad altri task dell'applicazione.Ciò è possibile scrivendo intenzionalmente delcodice che lancia altri thread di esecuzione in modotale che al processo (l'applicazione) venga allocatapiù di una porzione di tempo del processore. Seun'applicazione esegue più task in parallelo,l'applicazione è multithreaded(cioè utilizza più di un singolo thread perportare a termine il proprio lavoro) e la processazione ditask in parallelo in thread separati viene definitaasincrona.

La processazione asincrona viene utilizzata nella maggiorparte delle recenti tecnologie web. Ad esempio, Ajax èl'acronimo di Asynchronous JavaScript and XML.In AJAX, una chiamata asincrona al server viene eseguita inbackground ed è indipendente dal thread che staprocessando la pagina Web e che sta interagendo conl'utente, quindi la performance dell'interfacciautente viene incrmenetata e l'utente non deve piùattendere sulla chiamata effettuata al server ma vedrài risultati non appena sono pronti.

Silverlight e il processo Background Worker

Il .NET Framework fornisce la possibilità di lanciarepiù thread di esecuzione attraverso le classi presentinel namespace System.Threading. Al momentoSilverlight stesso include un namespaceSystem.Threading, ad ogni modo le classi inclusein questo namespace non sono state ancora implementate,quindi l'intenzione è rendere Silverlightmultithreaded ma bisognerà aspettare la prossimarelease.

Silverlight effettua alcune processazioni asincroneattraverso l'uso del processo background worker,anche se tale processo non è al momento controllabilee inoltre esegue i task usando un thread di esecuzionedifferente dal thread che gestisce l'interfaccia utente eSilverlight al momento non permette le chiamate fra i thread.

Invocare asincronamente un metodo web

Come detto poco fa, Silverlight non permette la comunciazionefra i thread ma utilizza il processo backgroundworker per effettuare le chiamate asincrone,specialmente quelle per i metodi web. Non servono modificheal Web service ASP.NET o WCF che viene invocatoasincronamente. Il codice invocato non si preoccupa seè stato invocato in modalità sincrona oasincrona, semplicemente viene eseguito. Ad ogni modo ilcodice invocante ha bissogno di alcune modifiche.

L'esempio mostrato qui sotto è stato utilizzato inun articolo precedente per implementare alcune misure disicurezza. Ad ogni modo, quando si clicca il bottone, non viè alcun ritardo visivamente riscontrabile mentre ilWeb service viene invocato e il suo metodo viene eseguito.Ecco come si presenta la pagina Silverlight.

Il codice presente in Page.xaml.cs che richiamail metodo Web, lo fa in modalità sincrona come segue.

public void GetPetInfo(object o, MouseEventArgs e) {  PISCLINQ.localhost.PetService svc = new PISCLINQ.localhost.PetService();  IEnumerable<string> pets = from petInfo in  svc.GetPetInfo(user.UserName, user.Password)     select petInfo;  // Mostra i risultati  foreach (string pet in pets)  {tbOutput.Text += pet;  }} 

Quando si utilizza un Web service ASP.NET o un servizio WCFaggiungendo un riferimento Web al progetto in Visual Studio,quest'ultimo crea una classe proxy che gestisce lacomunicazione fra la vostra applicazione e il metodo Web egestisce la serializzazione e la deserializzazione dei dati.La classe proxy creata include metodi per invocare un metodoWeb sia in modalità sincrona che asincrona. Quindi isoli cambiamenti di cui abbiamo veramente bisogno sono nelcodice che invoca il Web service: il codice mostrato poco faviene convertito come nel listato sottostante per effettuarechiamate asincrone.

public void GetPetInfo(object o, MouseEventArgs e) {    PISCLINQ.localhost.PetService svc = new PISCLINQ.localhost.PetService();    AsyncCallback asyncCall = new AsyncCallback(CallbackMethod);    svc.BeginGetPetInfo(user.UserName, user.Password, asyncCall, svc);} 

Nel codice appena mostrato, la seconda linea nel metodo creaun'istanza di un delegate che serve come metodocallback. La terza linea compie la chiamata asincrona almetodo Web e passa i parametri di input così come ilriferimento al metodo callback che il task richiameràquando avrà terminato il suo lavoro, e un riferimentoall'istanza del Web service utilizzato. Quando il taskè terminato, essendo la chiamata asincrona,Silverlight manterrà l'istanza del proxy Webservice in memoria e il metodo callback può usarlo perottenere il risultato del metodo. Il metodo callback vienemostrato nel codice sottostante.

private void CallbackMethod(IAsyncResult asyncResult) {  // Crea un'istanza del WebService  localhost.PetService svc = (localhost.PetService)asyncResult.AsyncState;  // Ottiene i risultati del WebMethod invocando  // il metodo della classe proxy  IEnumerable<string> pets = from petInfo in svc.EndGetPetInfo(asyncResult)     select petInfo;  // Mostra i risultati  foreach (string pet in pets)  {tbOutput.Text += pet;  }} 

Il codice LINQ è stato spostato nel metodo callbackdove sarà processato dopo che il metodo Webavrà completato l'esecuzione.

La classe HTTP Downloader

Silverlight include un'altra classe che viene usata perscaricare direttamente le risorse di un Web server, HTTPDownloader. Il nome di tale classe sarebbeDownloader ma ci si riferisce comunemente adessa come HTTP Downloader, che descrive meglio il suoutilizzo. Tale classe è concepita per scaricarerisorse di grosse dimensioni dal server, le quali potrebberorichiedere del tempo. Le chiamate effettuate daDownloader sono asincrone. Il codice sottostanteviene usato per scaricare un filmato denominatoLondonNewsCast.wmv.

using System;  using System.Windows;  using System.Windows.Controls;  using System.Windows.Documents;  using System.Windows.Ink;  using System.Windows.Input;  using System.Windows.Media;  using System.Windows.Media.Animation;  using System.Windows.Shapes;    namespace LondonVideo  {    public partial class Page : Canvas    {public void Page_Loaded(object o, EventArgs e)   {  // Richiesto per inizializzare le variabili  InitializeComponent();    // Scarica i dati  Downloader dl = new Downloader();  dl.Completed += new EventHandler(dl_Completed);  dl.Open("GET" , new Uri("LondonNewsCast.wmv" , UriKind.Relative));  dl.Send();}void dl_Completed(object sender, EventArgs e) {  Downloader dl = (Downloader)sender;  mediaLondon.SetSource(dl, "");}    }  }

Nel codice appena mostrato viene creata un'istanza dellaclasse Downloader. Proprio come per una chiamataasincrona ad un metodo Web, si deve fornire alla chiamata unafunzione callback. Nel codice presentato l'eventoCompleted è legato all'handlerdl_Completed.