This article has been localized into Spanish by the community.
El control DispatcherTimer
En WinForms hay un control llamado Timer que puede ejecutar una acción repetidas veces dentro de un intervalo de tiempo. WPF tiene esta posibilidad también, pero en vez de un control invisible, tenemos el control DispatcherTimer. Este control hace casi lo mismo, pero en vez de colocarlo en tu formulario, lo creas y utilizas exclusivamente desde el code-behind
La clase DispatcherTimer trabaja especificando un intervalo y suscribiéndolo al evento Tick que ocurrirá cada vez que se cumpla el intervalo. El DispatcherTimer no comienza hasta que llamas al método Start() o estableces la propiedad IsEnabled a verdadero.
Vamos a probar un simple ejemplo donde usamos DispatcherTimer para crear un reloj digital:
<Window x:Class="WpfTutorialSamples.Misc.DispatcherTimerSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DispatcherTimerSample" Height="150" Width="250">
<Grid>
<Label Name="lblTime" FontSize="48" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</Window>
using System;
using System.Windows;
using System.Windows.Threading;
namespace WpfTutorialSamples.Misc
{
public partial class DispatcherTimerSample : Window
{
public DispatcherTimerSample()
{
InitializeComponent();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += timer_Tick;
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
lblTime.Content = DateTime.Now.ToLongTimeString();
}
}
}
La parte XAML es extremadamente simple - consiste meramente en un elemento Label con una fuente de gran tamaño usada para mostrar el tiempo actual.
El Código-detrás es donde la magia ocurre en este ejemplo. En el constructor de la ventana creamos una instancia DispatcherTimer. Establecemos la propiedad Interval (Intervalo) a un segundo, subscribimos el evento Tick y entonces arrancamos el temporizador. En el evento Tick simplemente actualizamos el elemento Label para mostrar el tiempo actual.
Naturalmente el DispatcherTimer puede trabajar con intervalos más pequeños o mayores. Por ejemplo tu podrías desear que ocurriera cada 30 segundos o cada 5 minutos - para esto usa el método TimeSpan.From*, usando FromSeconds (para segundos) o FromMinutes (para minutos), o crea un nueva instancia TimeSpan que se adapte completamente a tus necesidades.
Para mostrar de los que es capaz el DispatcherTimer, vamos a tratar de actualizarlo con mayor frecuencia... ¡Mucha mayor frecuencia!
using System;
using System.Windows;
using System.Windows.Threading;
namespace WpfTutorialSamples.Misc
{
public partial class DispatcherTimerSample : Window
{
public DispatcherTimerSample()
{
InitializeComponent();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(1);
timer.Tick += timer_Tick;
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
lblTime.Content = DateTime.Now.ToString("HH:mm:ss.fff");
}
}
}
¡Como puedes ver, ahora le ordenamos al DispatcherTImer actuar cada milisegundo! En el evento Tick, usamos un formato personalizado de la cadena de tiempo para mostrar los milisegundos también en el elemento Label. Ahora tienes algo que podrías usar fácilmente como cronómetro - sólo añade un par de botones a la ventana y llama con ellos a los métodos Stop() (Parar), Start() (Iniciar) y Restart() (Reiniciar).
Resumen
Hay muchas ocasiones donde necesitas que algo ocurra a intervalos de tiempo dados y usando el DispatcherTimer esto es muy simple de conseguir. Sólo ten cuidado de que si haces algo complicado asociado al evento Tick no debería correr muy a menudo, como es el caso del último ejemplo donde el temporizador saltaba cada milisegundo - eso supondría un fuerte esfuerzo para el ordenador al ejecutar la aplicación.
También ten cuidado porque el DispatcherTimer no es 100% preciso en todas las situaciones. Las operaciones "tick" son ubicadas en la cola del Dispatcher de manera que si el ordenador está sometido a una gran presión, tu operación podría retrasarse. El framework .NET asegura que el evento Tick no se lanzará nunca demasiado pronto, pero no se puede asegurar que no se retrasará ligeramente. Sin embargo, en la mayoría de las ocasiones, el DispatcherTimer es lo suficientemente preciso.
Si necesitas que tu temporizador tenga una mayor prioridad en la cola, puedes establecer la DispatcherPriority (Prioridad) enviando uno de los valores a través de la prioridad del DispatcherTimer. Más información acerca de ello puedes encontrarlo en este artículo MSDN.