Technology Experience

Contenuti gestiti da Igor Damiani
posts - 949, comments - 2741, trackbacks - 15120

My Links

News

  • Questo blog si propone di raccogliere riflessioni, teoriche e pratiche, su tutto quello che riguarda il world-computing che mi sta attorno: programmazione in .NET, software attuale e futuro, notizie provenienti dal web, tecnologia in generale, open-source.

    L'idea è quella di lasciare una sorta di patrimonio personale, una raccolta di idee che un giorno potrebbe farmi sorridere, al pensiero di dov'ero e cosa stavo facendo.

    10/05/2005,
    Milano

Archives

Post Categories

Generale

Aggiornare un controllo da un thread: CurrentTimeUpdater

Nel mio (ormai famoso, dato che tutti mi chiedono notizie) software di fatturazione, ho aggiunto ieri sera una bella StatusBar, nel bordo inferiore della mia Windows Form con IsMdiContainer = true. Questa StatusBar non fa nulla di particolare, solo visualizzare l'ora corrente in basso a destra. Solo che l'ora va continuamente aggiornata perchè il tempo, non è una novità, passa e non si ferma mai.

Stamattina quindi ho creato una piccola classe CurrentTimeUpdater che in modo asincrono, e sfruttando un Timer interno, mi permette di aggiornare continuamente l'ora sul WF. Il vantaggio di questa soluzione è che il tutto gira in un thread secondario, senza appesantire la UI, mantenendo allo stesso tempo una certa semplicità. La classe CurrentTimeUpdater ha un solo costruttore, a cui vanno passati:

  1. un Control, che è quello su cui andrà scritta l'ora
  2. un double, che è l'intervallo in millisecondi che verrà impostato sul Timer interno
  3. un delegate, che punta alla funzione che aggiorna realmente il controllo

Girando in un thread secondario, ad ogni tick del Timer interno lancio il metodo BeginInvoke del controllo, così da evitare ogni sorta di problemi in questo senso. La classe inoltre implementa l'interfaccia IDisposable per rilasciare le risorse, primo fra tutti proprio il Timer. Sulla mia WF ho gestito l'evento Load così:

private void Form1_Load(object sender, EventArgs e)
{
    CurrentTimeUpdater wtc = 
new CurrentTimeUpdater(this, 1000,
        
new WriteCurrentTimeDelegate(WriteCurrentTime));
}

Il delegate WriteCurrentTimeDelegate punta ad una funzione implementata nella WF in questo modo:

private void WriteCurrentTime(DateTime CurrentTime)
{
    
this.lblOra.Text = CurrentTime.ToLongTimeString();
}

Senza grosse complicazioni, quindi, la mia classe CurrentTimeUpdater aggiorna la mia Label, gestendo correttamente l'accesso alla UI da parte del thread. Ho preferito aggiornare fisicamente il controllo sulla UI, perchè farlo nella mia classe avrebbe significato utilizzare sempre e solo la proprietà Text della classe Control. Dal momento che i controlli più complessi possono avere diverse possibilità, ho preferito utilizzare un delegate, che non fa altro che eseguire la function implementata. E' quindi compito della UI sapere come deve essere aggiornata. Vi riporto per brevità il codice dell'handler dell'evento Elapsed del Timer:

void TimerTick(object sender, System.Timers.ElapsedEventArgs e)
{
    
// Chiamo la BeginInvoke sul controllo
    
controlToWrite.BeginInvoke(updateFunction, e.SignalTime);
}

controlToWrite è il controllo. updateFunction è il delegate. SignalTime è una proprietà della classe ElapsedEventArgs, derivata da EventArgs, del FX. Nulla di particolarmente complicato.

Se a qualcuno dovesse servire, la classe CurrentTimeUpdater è disponibile a questo indirizzo.

powered by IMHO 1.2

Print | posted on Monday, April 3, 2006 12:26 PM | Filed Under [ Tecnologia ]

Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET