Multithreading in Silverlight 2.0

Cristian Civera

di Cristian Civera, in Silverlight 2.0, 3 febbraio 2009

Archiviato in: , ,

4 pagine in totale: <<Indietro 1 [2] 3 4 Avanti >>

Creazione e gestione dei Thread

Oggetto di questo articolo sono i thread ed è quindi giunta l'ora di vedere come è possibile crearli e gestirli. La necessità dovrebbe essere quella di poter eseguire operazioni lunghe, di calcolo computazionale o a causa di chiamate al mondo esterno, così da impedire che l'interfaccia ne risenta.

Un Thread in Silverlight (come in .NET) è rappresentato dall'omonima classe. Il costruttore accetta un delegate alla funzione (un puntatore ad essa) da eseguire e presenta metodi quali Start, Abort e Join per avviare, interrompere o attendere la fine dell'esecuzione di un Thread. Una volta avviato non è possibile sospenderlo e poi riavviarlo, e una volta giunto a conclusione, il thread muore. Il metodo Abort interrompe l'esecuzione non appena è possibile (non è detto che il thread termini istantaneamente) e scatena l'eccezione ThreadAbortException sul delegate che viene annullato così da notificare la richiesta.

La proprietà Name permette invece di dare un nome al thread per identificarlo meglio soprattutto nelle fasi di debug, mentre con ThreadState è possibile conoscere lo stato del thread (Running, Stopped, Aborted, ecc). Infine IsBackground, sebbene nelle applicazioni classiche del .NET Framework impedisce al processo di terminare se il thread non ha finito l'esecuzione, non sortisce nessun effetto nelle applicazioni Silverlight.

Detto questo ecco come eseguire una funzione su un nuovo Thread:

void newThread_Click(object sender, RoutedEventArgs e) 
{ 
    // Creo il thread 
    Thread thread = new Thread(ExecuteThread); 
    thread.Name = "test"; 
    // Avvio il thread 
    thread.Start(); 
    // Il thread UI prosegue senza aspettare ExecuteThread 
} 
 
void ExecuteThread() 
{ 
    // Eseguo operazione lunga 
    // Simulo con una funzione d'attesa 
    Thread.Sleep(TimeSpan.FromSeconds(5)); 
}

Nel codice precedente si noti la funzione statica Sleep che ferma il thread corrente (da evitare quindi sul thread UI), ritardando la sospensione del codice presente successivamente e quindi dell'intero thread.

La creazione manuale di un Thread non è un'attività a cui si ricorre spesso, prima di tutto perché crearne uno nuovo è un'attività impegnativa per il sistema operativo. Inoltre bisogna considerare che troppi Thread concorrenziali tra loro vanno a dividere le risorse della macchina ed il costo per lo switch tra un Thread all'altro che la CPU deve sostenere potrebbe addirittura peggiorare le performance di un algoritmo.

Infine, eventuali errori che avvengono su Thread diversi da quello principale terminano l'esecuzione dello stesso ma non minano la normale funzionalità dell'applicazione. In questo caso infatti viene scatenato l'evento Application.UnhandledException normalmente intercettato dal template predefinito di Visual Studio, il quale se in fase di debug ignora l'errore, altrimenti lo rilancia nel browser notificando l'utente. E' quindi sempre buona norma prevedere eventuali errori, almeno a livello di applicazione con tale evento.

Utilizzo del Thread pool

Nella maggior parte dei casi, essendo un'applicazione Silverlight, quello che serve veramente allo sviluppatore è compiere operazioni asincrone, che non blocchino l'attività dell'utente, ma che semplicemente interroghino servizi in remoto, effettuano chiamate REST o eseguano operazioni su socket. Per facilitare l'esecuzione di codice in asincrono quindi, in Silverlight come nel .NET Framework è presente un pool di Thread già pronti all'uso, che una volta eseguita l'operazione ad essi assegnati, ritornano nel pool pronti per essere riutilizzati una seconda volta. In questo modo non si paga l'operazione di creazione del Thread, ne si rischia di intasare l'applicazione. La classe che permette tutto ciò è ThreadPool del namespace System.Threading che mette a disposizione in modo predefinito un minimo di un Thread per core ed eventualmente se richiesto, fino ad un massimo di 250 Thread per core, entrambi comunque configurabili con i metodi SetMinThreads e SetMaxThreads.

Il metodo principale è QueueUserWorkItem che accetta un delegate di tipo WaitCallback ed eventualmente un parametro di stato che viene poi passato alla funzione.

void startOnThreadPool_Click(object sender, RoutedEventArgs e) 
{ 
    ThreadPool.QueueUserWorkItem(OnThreadPool); 
} 
 
void OnThreadPool(object state) 
{ 
    // Eseguo 
}

La tecnica è piuttosto semplice, ma va tenuto in considerazione che non è detto che appena chiamato il metodo QueueUserWorkItem il delegate venga eseguito, dipende se il pool ha un Thread libero per farlo.

Nel .NET Framework è inoltre disponibile la possibilità di invocare un delegate sul ThreadPool di qualsiasi definizione usando il metodo BeginInvoke. Su Silverlight questo non è possibile e sebbene il metodo esiste, scatenerà un NotSupportedException a runtime.

4 pagine in totale: <<Indietro 1 [2] 3 4 Avanti >>

Contenuti dell'articolo

Commenti

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.



Segnala su: Facebook MSDN Social Twitter Segnalo Wikio Diggita Technorati Stumbleupon Google Yahoo FriendFeed Delicious Furl

TUTORIALS
TOP TEN ARTICOLI
ARTICOLI VIA E-EMAIL

Iscriviti alla nostra newsletter nuoviarticoli per ricevere via e-mail le notifiche!

MEDIA
IN EVIDENZA
MISC