Redazione
a- a+

Silverlight: migliorare la performance delle applicazioni

Silverlight: migliorare la performance delle applicazioni

I computer che contengono un solo processore sono capaci di eseguire solo un singolo task per volta. In questo caso, come fa un sistema operativo elaborato come Windows ad eseguire operazioni concorrenti così come ospitare in memoria più applicazioni simultaneamente, ognuna delle quali svolge un proprio compito? La risposta è che il sistema operativo gestisce ciclicamente e molto efficacemente il tempo che il processore assegna ad ogni singolo processo, permettendo ad ognuno di loro di essere eseguito a turno per un brevissimo periodo di tempo. Questo dà l'illusione che il tutto avvenga simultaneamente e contemporaneamente.

Ogni processo tipicamente tenta di eseguire un singolo task per cui ciascun processo viene assegnato ad un singolo thread di esecuzione (una porzione del tempo del processore) per completare il proprio task. La maggior parte del codice viene scritto per eseguire un singolo task alla volta e per completarlo prima di passare ad un altro. Questo tipo di processazione viene definita sincrona. Nella maggior parte degli scenari, l'esecuzione sincrona del codice è piuttosto veloce e sufficiente per i task più comuni. Inoltre molte volte, alcuni task dipendono dal completamento di un task precedente, ad esempio quando si interroga un database, la query non può esser eseguita fintanto che non si stabilisce una connessione con il database.

Ad ogni modo esistono alcuni task eseguiti nel codice che non dipendono da altri task per essere completati. Quando i task possono essere processati indipendentemente, si incrementa la performance se il task può essere eseguito parallelamente ad altri task dell'applicazione. Ciò è possibile scrivendo intenzionalmente del codice che lancia altri thread di esecuzione in modo tale che al processo (l'applicazione) venga allocata più di una porzione di tempo del processore. Se un'applicazione esegue più task in parallelo, l'applicazione è multithreaded (cioè utilizza più di un singolo thread per portare a termine il proprio lavoro) e la processazione di task in parallelo in thread separati viene definita asincrona.

La processazione asincrona viene utilizzata nella maggior parte delle recenti tecnologie web. Ad esempio, Ajax è l'acronimo di Asynchronous JavaScript and XML. In AJAX, una chiamata asincrona al server viene eseguita in background ed è indipendente dal thread che sta processando la pagina Web e che sta interagendo con l'utente, quindi la performance dell'interfaccia utente 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 lanciare più thread di esecuzione attraverso le classi presenti nel namespace System.Threading. Al momento Silverlight stesso include un namespace System.Threading, ad ogni modo le classi incluse in questo namespace non sono state ancora implementate, quindi l'intenzione è rendere Silverlight multithreaded ma bisognerà aspettare la prossima release.

Silverlight effettua alcune processazioni asincrone attraverso l'uso del processo background worker, anche se tale processo non è al momento controllabile e inoltre esegue i task usando un thread di esecuzione differente dal thread che gestisce l'interfaccia utente e Silverlight al momento non permette le chiamate fra i thread.

Invocare asincronamente un metodo web

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

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

Il codice presente in Page.xaml.cs che richiama il 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 WCF aggiungendo un riferimento Web al progetto in Visual Studio, quest'ultimo crea una classe proxy che gestisce la comunicazione fra la vostra applicazione e il metodo Web e gestisce la serializzazione e la deserializzazione dei dati. La classe proxy creata include metodi per invocare un metodo Web sia in modalità sincrona che asincrona. Quindi i soli cambiamenti di cui abbiamo veramente bisogno sono nel codice che invoca il Web service: il codice mostrato poco fa viene convertito come nel listato sottostante per effettuare chiamate 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 crea un'istanza di un delegate che serve come metodo callback. La terza linea compie la chiamata asincrona al metodo Web e passa i parametri di input così come il riferimento al metodo callback che il task richiamerà quando avrà terminato il suo lavoro, e un riferimento all'istanza del Web service utilizzato. Quando il task è terminato, essendo la chiamata asincrona, Silverlight manterrà l'istanza del proxy Web service in memoria e il metodo callback può usarlo per ottenere il risultato del metodo. Il metodo callback viene mostrato 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 callback dove sarà processato dopo che il metodo Web avrà completato l'esecuzione.

La classe HTTP Downloader

Silverlight include un'altra classe che viene usata per scaricare direttamente le risorse di un Web server, HTTP Downloader. Il nome di tale classe sarebbe Downloader ma ci si riferisce comunemente ad essa come HTTP Downloader, che descrive meglio il suo utilizzo. Tale classe è concepita per scaricare risorse di grosse dimensioni dal server, le quali potrebbero richiedere del tempo. Le chiamate effettuate da Downloader sono asincrone. Il codice sottostante viene usato per scaricare un filmato denominato LondonNewsCast.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 della classe Downloader. Proprio come per una chiamata asincrona ad un metodo Web, si deve fornire alla chiamata una funzione callback. Nel codice presentato l'evento Completed è legato all'handler dl_Completed.



Ti potrebbe interessare anche

commenta la notizia

C'è 1 commento
Staff
Ti interessano altri articoli su questo argomento?
Chiedi alla nostra Redazione!