Multithreading in Silverlight 2.0
di Cristian Civera, in Silverlight 2.0, 3 febbraio 2009
4 pagine in totale: <<Indietro 1 2 3 [4]
Il secondo pattern, già presente sin dal .NET Framework 1.0, consiste nel mettere a disposizione da parte della classe, due metodi Begin[Operazione] e End[Operazione]. Il primo accetta, sempre per convenzione, un AsyncCallback alla funzione da chiamare una volta terminata l'operazione, e un oggetto di stato. Restituisce poi un IAsyncResult, interfaccia di riferimento per l'operazione appena avviata, con il quale è possibile conoscere se l'operazione è già conclusa tramite la proprietà IsCompleted.
Ciò che il pattern poi prevede è chiudere la chiamata per avere il risultato con la funzione End che accetta IAsyncResult restituito dal corrispettivo Begin. E' possibile chiamare subito dopo la Begin il metodo di End fermando quindi il thread (solitamente quello dell'interfaccia) fino a quando la chiamata non è conclusa. In alternativa, ed è strada consigliata, è possibile chiamare il metodo di End nel callback passato in fase di Begin che viene invocato sul ThreadPool solo al termine dell'operazione. Di conseguenza bisogna prestare attenzione ad eventuali interventi che si fanno sull'interfaccia. Poiché la chiamata all'End va effettuata sulla stessa istanza della classe, occorre mantenere un riferimento usando un campo a livello della propria classe o usando il parametro di stato del metodo di Begin.
Riassumendo ecco come si può chiamare la classe WebRequest (rispetto a WebClient permette il pieno controllo di header, ecc) per una chiamate HTTP:
void callHttp_Click(object sender, EventArgs e) { WebRequest request = HttpWebRequest.Create(new Uri("http://www.aspitalia.com")); // Avvio in asincrono la richiesta // Mantengo request come parametro di stato request.BeginGetResponse(OnGetResponse, request); } void OnGetResponse(IAsyncResult ar) { // Recupero dallo stato la request WebRequest request = (WebRequest)ar.AsyncState; try { // Termino la chiamata WebResponse response = request.EndGetResponse(ar); resultTextBlock.Text = "Terminato"; } catch (Exception ex) { resultTextBlock.Text = "Errore nell'esecuzione: " + ex.Message; } }
Si noti che, generalmente, eventuali errori avvenuti nell'operazione asincrona vengono scatenati sull'End perciò occorre prevedere questa possibilità.
Sincronizzazione dei Thread
Come si può avere intuito fino ad adesso, i Thread sono molto comodi, ma vanno usati con cautela perché possono influire negativamente sulle prestazioni e non vanno d'accordo con il motore di rendering di Silverlight.
Oltre a questo occorre però prestare attenzione ad eventuali conflitti tra i Thread. Per esempio, due o più Thread potrebbero lavorare su una variabile e in funzione di essa effettuare delle elaborazioni, per poi magari reimpostare quelle variabili. Purtroppo, per quanto in C# o in VB l'istruzione di assegnazione possa sembrare unica e atomica, essa si trasforma in più istruzioni della CPU che per via della concorrenzialità dei Threads potrebbero essere suddivise in più parti con risultati inattesi. Questo tipo di comportamento sarebbe molto difficile da individuare, perché occasionale e influenzabile dalla tipologia di macchina e dallo stress a cui essa è sottoposta.
Inoltre anche al di là della singola assegnazione, il codice potrebbe effettuare alcune operazioni a fronte di alcune informazioni lette che di fatto non sono più valide.
Per ovviare a questo problema esistono della classi per eseguire alcune semplici operazioni in modo atomico, senza rischio e il più veloce possibile. La classe Interlocked ha appunto una serie di metodi statici quali Add, CompareExchange, Decrement, Increment ed Exchange per aggiungere, comparare, diminuire, incrementare o cambiare numeri o oggetti.
Il seguente esempio incrementa un contatore in modo atomico, sicuro dalle concorrenze di altri Thread:
// Invece di: count = count + 1; Interlocked.Increment(ref count);
Qualora l'unità da rendere thread safe coinvolgesse più istruzioni complesse, esiste un semaforo rappresentato dalla classe Monitor per acquisire il controllo in funzione di un puntatore e rilasciarlo quando terminati. In C# e esiste una sintassi specifica che sfrutta la parola chiave lock:
// Acquisisco il lock in base alla classe stessa lock (this) { if (count > 100) count = 0; count = count + 1; }
Nell'esempio precedente quando un ipotetico Thread A esegue il lock, impedisce ad eventuali Thread B, C ecc di andare avanti, fino a quando le istruzioni contenute tra le graffe si concludono. L'oggetto passato a lock dev'essere un valore di riferimento come una classe o un object creato appositamente che rappresenta l'identificativo del lock che si vuole effettuare (riferimenti diversi permettono di creare diversi semafori a scopi diversi).
Conclusioni
Il Threading è una parte di Silverlight che obbligatoriamente si utilizza se l'applicazione ha un minimo di interrogazione dati che sfrutta qualunque tecnologia disponibile su HTTP o Socket. Conoscere come funziona, quali sono le varie tecniche di gestione dei Thread e gli eventuali errori o problematiche che si possono incontrare permette di scrivere applicazioni robuste che non danno frustrazioni all'utente con inutili "congelamenti" o errori bloccanti.
4 pagine in totale: <<Indietro 1 2 3 [4]
Contenuti dell'articolo
Sullo stesso argomento
-
Applicazioni Silverlight con il cloud computing su Windows Azure
-
Aggiungere interattività al controllo Chart di Silverlight 3.0
-
Realizzare un sito completo in Silverlight: una galleria fotografica
-
Supporto audio e video in Silverlight 3.0
-
Effetti speciali sulle immagini in Silverlight 3.0
-
Anteprima di Expression Blend 3.0
-
Le novità di Silverlight 3.0 beta 1
-
Realizzare un menu riutilizzabile utilizzando DataTemplate e DataBinding
-
Un tocco di stile alle applicazioni Silverlight: style e template

















Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.