Un Timer est un objet permettant de déclencher une action à intervalle régulier. C'est une sorte de minuterie.
En WPF, il existe un timer bien particulier, nommé DispatcherTimer permettant d'effectuer ces actions sur le Thread UI.
Dans cet article, nous l'étudions plus en détails !
Pourquoi utiliser un DispatcherTimer ?
Vous le savez surement, en WPF il y a un thread principal sur lequel le rendu graphique est effectué. Aussi, si vous souhaitez accéder ou modifier un élément de l'interface graphique alors il faut être sur ce Thread. C'est une obligation imposée par le framework.Le DispatcherTimer permet ainsi de déclencher un Timer qui sera exécuté sur le Thread principal. Il pourra ainsi accéder aux éléments de l'interface graphique.
Prenons un exemple concret afin d'illustrer cette théorie : nous allons créer une application toute simple permettant d'incrémenter une valeur toutes les secondes. C'est
Si nous ne connaisons pas les Timers alors l'idée qui vient à notre esprit et de bloquer le Thread en utilisant la méthode Thread.Sleep de cette façon :
while (_valeurInt < 40)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
_valeurInt++;
_valeur.Text = _valeurInt.ToString(CultureInfo.InvariantCulture);
}
Comment utiliser le DispatcherTimer ?
L'idée est alors d'utiliser le DispatcherTimer pour mettre à jour la valeur. Pour cela il faut définir un intervalle de temps : c'est l'écart qu'il y aura entre chaque execution. Celui-ci est représenté sous la forme de la propriété Interval. Attention, cette valeur n'est pas précise et il faut recourir à d'autres méchanismes si l'on souhaite une précision extrême.
La classe DispatcherTimer définit aussi un événement appelé Tick : il sera déclenché à la fin de chaque intervalle de temps et est executé sur le Dispatcher. C’est donc à lui qu’il faut s’abonner pour définir le traitement à effectuer.
Une instance de DispatcherTimer défini aussi les méthodes start et stop permettant de le démarrer et de l’arrêter.
Voici alors l'exemple complet reproduisant notre compte à rebour inversé mais sans blocage de l'interface utilisateur :
private void StopTimer()
{
if (timer != null)
{
//Arrêt du timer
timer.Stop();
}
timer = null;
}
private void StartTimer()
{
//Création du timer
if (timer == null)
{
timer = new DispatcherTimer(DispatcherPriority.ContextIdle);
}
//Déclenchement toutes les secondes
timer.Interval = TimeSpan.FromSeconds(1);
//La méthode TimerTick sera appelée toutes les secondes
timer.Tick += TimerTick;
//On démarre le Timer
timer.Start();
}
private int _valeurInt = 0;
void TimerTick(object sender, EventArgs e)
{
//Incrémentation de la valeur
_valeurInt++;
//Changement du contrôle
_valeur.Text = _valeurInt.ToString(CultureInfo.InvariantCulture);
}
Aller plus loin avec le DispatcherTimer
Une fois que l’on maîtrise bien ces concepts de base, on peut aller encore plus loin en définissant une priorité à utiliser pour l’execution des gestionnaires d’événement attaché à Tick.
Cela est fait via le constructeur :
timer = new DispatcherTimer(DispatcherPriority.ContextIdle);
Aussi, il est possible d’associer un objet à un timer qui pourra être retrouvé à l’éxecution de la méthode de traitement. C’est une façon de passer des paramétres. Voici un exemple :
//Définition de la valeur de Tag
timer.Tag = "Une valeur";
//Plus loin dans le gestionnaire d'événement de Tick
void TimerTick(object sender, EventArgs e)
{
var timer = sender as DispatcherTimer;
var valeur = timer.Tag;
Console.WriteLine("Valeur retrouvée : "valeur);
}
En espérant que cela vous éclairera ![]()
Bon code !
| Suivant > |
|---|





