-
异步杂项:

DispatcherTimer

在WinForms中,有一个名为Timer的控件,它可以在给定的时间间隔内重复执行一个动作。 WPF也能实现,我们有DispatcherTimer控件,但不是一个不可见的控件。 用途完全相同,但不能将其放在窗口上,而是从后台代码中专门创建和使用它。

DispatcherTimer类通过指定间隔然后订阅每次满足此间隔时将发生的Tick事件来工作。 在调用Start()方法或将IsEnabled属性设置为IsEnabled之前,DispatcherTimer不会启动。

让我们尝试一个简单的例子,我们使用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部分非常简单 - 它只是一个大字体的居中标签,用于显示当前时间。

后台代码是这个例子中发生神奇的地方。 在窗口的构造函数中,我们创建一个DispatcherTimer实例。 我们将Interval属性设置为一秒,订阅Tick事件,然后我们启动计时器。 在Tick事件中,我们更新标签以显示当前时间。

当然,DispatcherTimer可以用更小或更大的时间间隔工作。 您可能只希望每30秒或5分钟发生一次 - 只需使用TimeSpan.From*方法,如FromSeconds或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每毫秒启动一次! 在Tick事件中,我们使用自定义时间格式字符串在标签中显示毫秒数。 现在你有了一些可以很容易地用成秒表的东西 - 只需在窗口中添加几个按钮,然后让它们调用定时器上的Stop()Start()Restart()方法。

小结

在许多情况下,您需要在应用程序中以给定的间隔做些什么事情,使用DispatcherTimer,它很容易实现。 请注意,如果你在Tick事件中做了一些复杂的事情,它不应该经常运行,就像最后一个计时器每毫秒计时一样的例子 - 这将给运行你的应用程序的计算机带来沉重的压力。

另请注意,DispatcherTimer并不是在所有情况下都100%精确。 tick操作放在Dispatcher队列中,如果计算机承受很大压力,您的操作可能会延迟。 .NET框架承诺Tick事件永远不会发生得太早,但不能保证它不会稍微延迟。 但是对于大多数案例,DispatcherTimer非常精确。

如果您需要计时器在队列中具有更高的优先级,则可以通过在DispatcherTimer优先级上发送其中一个值来设置DispatcherPriority。 有关它的更多信息可以在这篇MSDN文章中找到。