TOC

This article is currently in the process of being translated into Polish (~25% done).

Misc.:

The DispatcherTimer

In WinForms, there's a control called the Timer, which can perform an action repeatedly within a given interval. WPF has this possibility as well, but instead of an invisible control, we have the DispatcherTimer control. It does pretty much the same thing, but instead of dropping it on your form, you create and use it exclusively from your Code-behind code.

The DispatcherTimer class works by specifying an interval and then subscribing to the Tick event that will occur each time this interval is met. The DispatcherTimer is not started before you call the Start() method or set the IsEnabled property to true.

Spójrzmy na prosty przykład gdzie użyjemy DispatcherTimer do stworzenia zegara cyfrowego:

<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();
		}
	}
}

The XAML part is extremely simple - it's merely a centered label with a large font size, used to display the current time.

Code-behind is where the magic happens in this example. In the constructor of the window, we create a DispatcherTimer instance. We set the Interval property to one second, subscribe to the Tick event and then we start the timer. In the Tick event, we simply update the label to show the current time.

Oczywiście, DispatcherTimer może działać dla znacznie mniejszych lub znacznie większych interwałów. Na przykład: możesz chcieć żeby coś działo się co 30 sekund lub co 5 minut - po prostu użyj odpowiedniej metody TimeSpan.From*, takiej jak TimeSpan.FromSeconds lub TimeSpan.FromMinutes, lub stwórz nową instancję TimeSpan dopasowaną do twoich potrzeb.

By pokazać, do czego zdolny jest DispatcherTimer, spróbujmy aktualizować go częściej... Znacznie częściej!

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");
		}
	}
}

Jak widzisz, teraz możemy odpytywać DispatcherTimer by aktywował się co milisekundę! W zdarzeniu Tick, używamy odpowiedniego formatowania stringa, aby w wyświetlanym tekście uwzględnić również milisekundy. Właśnie stworzyłeś coś, co po kilku drobnych poprawkach można by nazwać stoperem - po prostu dodaj kilka przycisków do okienka, które po kliknięciu wywołają odpowiednie metody timera: Stop(), Start() i Restart()

Summary

There are many situations where you would need something in your application to occur at a given interval, and using the DispatcherTimer, it's quite easy to accomplish. Just be aware that if you do something complicated in your Tick event, it shouldn't run too often, like in the last example where the timer ticks each millisecond - that will put a heavy strain on the computer running your application.

Also be aware that the DispatcherTimer is not 100% precise in all situations. The tick operations are placed on the Dispatcher queue, so if the computer is under a lot of pressure, your operation might be delayed. The .NET framework promises that the Tick event will never occur too early, but can't promise that it won't be slightly delayed. However, for most use cases, the DispatcherTimer is more than precise enough.

If you need your timer to have a higher priority in the queue, you can set the DispatcherPriority by sending one of the values along on the DispatcherTimer priority. More information about it can be found on this MSDN article.

This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!