#159 - Gestire code di operazioni con un Dispatcher personalizzato
di Cristian Civera, in Windows Presentation Foundation, .NET Framework, 29 gennaio 2010
Archiviato in: .NET Framework, .NET Framework 3.0, .NET Framework 3.5, Windows Presentation Foundation
Nella programmazione di applicazioni Windows è frequente l'uso di operazioni asincrone per evitare il blocco dell'interfaccia. Utilizzare il pattern Begin/End Invoke o il ThreadPool sono le tecniche più comuni e permettono di accodare la richiesta e di eseguirla non appena un thread è libero. L'alternativa è quella di creare un Thread personalizzato ed eseguire un delegate, ma in ogni caso come per il thread pool non si ha a disposizione un controllo delle operazioni nel caso queste siano più di una e necessittano un raggruppamento logico tale da eseguirle una dietro l'altra.
L'esigenza che si ha è quella quindi di avere un unico thread dove accodare le operazioni da eseguire una dopo l'altra. In WPF per coprire questa esigenza si può utilizzare il Dispatcher che, normalmente utilizzato per le operazioni di UI sul thread principale, può essere sfruttato anche su altri thread per innescare una coda mono thread.
Il Dispatcher non è altro che un loop infinito che gira all'interno di un thread in attesa di eseguire operazioni, perciò quello che serve per crearne uno personalizzato è istanziare prima di tutto un Thread nel quale girare:
public class OperationsQueue { private Thread queueThread; private Dispatcher dispatcher; private ManualResetEvent createEvent = new ManualResetEvent(false); public OperationsQueue() { // Creo il thread queueThread = new Thread(RunQueue); queueThread.IsBackground = true; queueThread.Start(); // Aspetto che il dispatcher sia avviato createEvent.WaitOne(); }
Il ManualResetEvent è un semaforo e viene utilizzato per accertarsi che il Dispatcher parta e sia pronto all'uso. Il metodo che infatti si invoca nel nuovo Thread esegue la funzione Run per avviare il loop e notificare l'avvio.
private void RunQueue() { // Riferimento al dispatcher in base al thread corrente dispatcher = Dispatcher.CurrentDispatcher; // Notifico che il motore è partito dispatcher.BeginInvoke(new Action(() => createEvent.Set())); // Avvio il loop, da qua il thread non esce Dispatcher.Run(); }
A questo punto è tutto pronto ed è possibile fornire la classe di un metodo per l'accodamento delle operazioni, semplicemente invocando BeginInvoke.
public void QueueInternal(Action action) { this.dispatcher.BeginInvoke(action, priority); }
L'uso del Dispatcher offre inoltre molteplici vantaggi: oltre ad un sistema solido, possiamo gestire le priorità delle operazioni, abortirle se non sono state ancora eseguite e gestire in modo univoco gli eventuali errori generati. Infine, essendo il Thread di tipo Background, una volta che il processo viene chiuso anche la coda muore con esso.
Approfondimenti
-
Windows Server AppFabric va in beta 2
-
L'accesso ai dati nell'era del cloud computing con Windows Azure
-
#115 - Creare file ZIP con System.IO.Packaging
-
#130 - Effettuare una query XPath con LINQ To XML
-
#127 - Ospitare i controlli Windows Forms in un'applicazione WPF
-
Le problematiche più comuni di un'architettura M-V-VM con WPF
-
#107 - Passare un Expression di Entity Framework attraverso un servizio WCF
-
#138 - Estrarre un subset di oggetti da una lista non generica con LINQ
-
#139 - Invocare servizi in asincrono con WCF
-
#168 - Recuperare tutte le istanze di un tipo specifico con Entity Framework ed Entity SQL
-
#157 - Serializzare e deserializzare in JSON con DataContractJsonSerializer
-
#1004 - Utilizzare le DataAnnotation con ASP.NET Dynamic Data Controls

















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