2010-02-13 13 views
21

Si prega di spiegare la differenza tra "DispatcherTimer" e "un normale Timer" che @Kent Boogaart intendeva utilizzare in un'app WPF multithreading come task sheduler in questo argomento:DispatcherTimer rispetto a un timer normale nell'app WPF per un pianificatore di attività

Advice needed for multi-threading strategy for WPF application

nei commenti a uno dei post (citazione):

-Se tutto il DispatcherTimer fa è dare il via un altro thread, qual è il punto di utilizzare il DispatcherTimer? .... questi thread non devono essere avviati sul thread dell'interfaccia utente. Potresti semplicemente usare un normale Timer ed evitare di interrompere completamente l'interfaccia utente

Che cosa si intende per "timer normale"? In che modo ("DispatcherTimer" e "un timer normale") differiscono per quanto riguarda il loro impatto sull'interfaccia utente?

(Fino a quando la lettura di questo post ho pensato DispatcherTimer come un modo naturale di utilizzare i timer in WPF. Qual è il caso in cui questo non è vero?)

risposta

39

DispatcherTimer è il timer regolare. Spara il suo evento Tick sul thread dell'interfaccia utente, puoi fare tutto ciò che vuoi con l'interfaccia utente. System.Timers.Timer è un timer asincrono, il suo evento Elapsed viene eseguito su un thread pool di thread. Devi essere molto attento nel tuo gestore di eventi, non ti è permesso toccare alcun componente dell'interfaccia utente o variabili legate ai dati. E dovrai usare l'istruzione di blocco ovunque tu abbia accesso ai membri della classe che sono anche usati nel thread dell'interfaccia utente.

Nella risposta collegata, la classe Timer era più appropriata perché l'OP stava cercando di eseguire il codice in modo asincrono di proposito.

+0

nota che 'tocca' include l'impostazione MVVM proprietà ViewModel in modo che quando si utilizza un DispatcherTimer stai bene, ma con un timer non si può nemmeno farlo –

26

L'evento Tick del timer regolare viene effettivamente attivato nel thread in cui è stato creato il timer, quindi nell'evento tick, per accedere a qualsiasi cosa con l'interfaccia utente, è necessario passare attraverso dispatcher.begininvoke come indicato di seguito.

RegularTimer_Tick(object sender, EventArgs e) 
{ 
    txtBox1.Text = "count" + i.ToString(); 
    // error can not access 
    // txtBox1.Text property outside dispatcher thread... 

    // instead you have to write... 
    Dispatcher.BeginInvoke((Action)delegate(){ 
     txtBox1.Text = "count " + i.ToString(); 
    }); 
} 

In caso di Dispatcher timer, è possibile accedere agli elementi di interfaccia utente senza fare iniziare Invoke o invocare come seguire ...

DispatcherTimer_Tick(object sender, EventArgs e) 
{ 
    txtBox1.Text = "Count " + i.ToString(); 
    // no error here.. 
} 

DispatcherTimer solo fornisce la convenienza sopra Timer regolare di accedere a oggetti dell'interfaccia utente facilmente.

+1

Grazie per gli esempi di codice, uno – rem

+0

è Timer dispatcher utilizzando Invoke o BeginInvoke? –

+0

In base all'origine, DispatcherTimer utilizza BeginInvoke, la coda del dispatcher ha un meccanismo di richiamo basato sulla priorità. http://referencesource.microsoft.com/#WindowsBase/Base/System/Windows/Threading/DispatcherTimer.cs,d2a05f6b09eee858 –

14

Con .NET 4.5 è anche possibile creare un delegato async per il timer se è necessario utilizzare la nuova funzionalità .NET 4.5 await.

 var timer = new DispatcherTimer(); 
     timer.Interval = TimeSpan.FromSeconds(20); 
     timer.Tick += new EventHandler(async (object s, EventArgs a) => 
     { 
      Message = "Updating..."; 
      await UpdateSystemStatus(false); 
      Message = "Last updated " + DateTime.Now;    
     }); 
     timer.Start(); 
+0

questo potrebbe anche essere di interesse (la mia domanda in cerca di un DispatcherTimer asincrono amichevole) http://stackoverflow.com/domande/12442622/async-aware-friendly-DispatcherTimer-involucro-sottoclasse/12442719 # 12442719 –

Problemi correlati