TOC

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

Misc.:

The DispatcherTimer

В Windows Forms існує компонент Timer який може виконувати вказаний код з певною періодичністю. В WPF теж є така можливість, але замість невидомого компоненту використовується клас DispatcherTimer. Він робить майже те саме, але замість додавання компоненту на форму об'єкти даного класу створюються виключно вручну в коді програми.

Для роботи з об'єктом класу DispatcherTimer потрібно задати проміжок часу між викликами бажаної функції і підписатися на подію Tick яка виникає кожного разу коли спливає вказаний час. Таймер не запуститься доти доки не буде викликано методу Start() або властивість IsEnabled об'єкту не набуде значення true.

Давай спробуємо написати просту програму в якій ми будемо використовувати DispatcherTimer для того щоб створити цифровий годинник:

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

Розмітка XAML дуже проста — це лише відцентрований компонент Label на якому відображається поточний час.

В коді програми в методі–конструкторі вікна ми створюємо екземляр класу DispatcherTimer. Ми також встановлюємо властивість Interval в одну секунду, підписуємося на подію Tick і запускаємо таймер. В функції яка відповідає за обробку події Tick ми просто оновлюємо значення Label для того щоб відобразити поточний час.

Звісно ж DispatcherTimer може працювати з яким завгодно інтервалом. Можна встановити таймер в 30 секунд або в 5 хвилин — просто використовуй такі методи TimeSpan.From* як FromSeconds or FromMinutes, або створи новий об'єкт класу TimeSpan і налаштуй його так як тобі потрібно.

Для того щоб показати на що здатен клас DispatcherTimer спробуємо збільшити частоту оновлення.

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

Тепер відповідна подія об'єкту класу DispatcherTimer викликається набагато частіше — кожну мілісекунду. Ми також змінили формат відображення часу для того щоб показувати ще й мілісекунди. Дану програму можна легко перетворити на секундомір додавши декілька кнопок які будуть викликати методи Stop(), Start() і Restart().

Підсумок

Клас DispatcherTimer дозволяє доволі легко писати код з таймерами. Тільки май на увазі що функцію, виконання якої може зайняти багато часу, не слід викликати занадто часто як, наприклад, в нашому прикладі оскільки це може погано вплинути на роботу ЕОМ,

Також май на увазі що DispatcherTimer не завжди гарантує абсолютну точність. Заплановані події таймера потрапляють в чергу на виконання спеціальному об'єкту Dispatcher (наслідується від класу DispatcherObject) який володіє потоком програми і керує черговістю елементів роботи. Тому якщо, наприклад, ЦП дуже зайнятий, то виконання події може бути відкладено. .NET обіцяє що подія Tick ніколи не виникне занадто рано, але не обіцяє що її не буде відкладено на невідомий час. Однак, для більшості випадків точності DispatcherTimer більш ніж достатньо.

Використовуючи значення з переліку DispatcherPriority можна задавати пріорітет функції в черзі (знадобиться якщо, наприклад, потрібен вищий пріорітет виконання).

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!