
在现代应用程序开发中,定时任务是一个常见需求。无论是定期获取数据、执行后台任务,还是刷新界面,定时器都是必不可少的工具。.NET 6 引入了一个新的定时器类——PeriodicTimer,它为开发者提供了一种简单而高效的方法来处理周期性任务。在这篇博客中,我们将了解PeriodicTimer,并展示如何在实际应用中使用它。
PeriodicTimer是.NET 6中引入的一个定时器类,用于周期性触发操作。与传统的System.Threading.Timer不同,PeriodicTimer专为异步任务设计,利用async/await模式使代码更加简洁和易于维护。
PeriodicTimer与异步编程模式完美结合,支持async/await,使代码更易读,减少了回调地狱。
PeriodicTimer在等待下一个周期时不消耗CPU资源,因为它利用了异步等待机制。
当不再需要定时器时,只需取消关联的CancellationToken,不需要像传统定时器那样显式调用停止方法。
下面我们来看一个简单的例子,展示如何使用PeriodicTimer每隔一秒输出一条消息。
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
using PeriodicTimer timer = new PeriodicTimer(TimeSpan.FromSeconds(1));
CancellationTokenSource cts = new CancellationTokenSource();
Task.Run(() =>
{
// 5秒后取消定时器
Thread.Sleep(5000);
cts.Cancel();
});
try
{
while (await timer.WaitForNextTickAsync(cts.Token))
{
Console.WriteLine($"Tick at {DateTime.Now}");
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Timer was cancelled.");
}
}
}
在WPF应用程序中,我们可以使用PeriodicTimer来定期更新UI元素。下面是一个简单的示例,展示如何在WPF中使用PeriodicTimer来每秒更新一次文本框的内容。
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace WpfAppWithPeriodicTimer
{
public partial class MainWindow : Window
{
private readonly CancellationTokenSource _cts = new();
public MainWindow()
{
InitializeComponent();
StartTimer();
}
private async void StartTimer()
{
using PeriodicTimer timer = new PeriodicTimer(TimeSpan.FromSeconds(1));
try
{
while (await timer.WaitForNextTickAsync(_cts.Token))
{
// 更新UI需要在UI线程上执行
Dispatcher.Invoke(() =>
{
MyTextBox.Text = $"Updated at {DateTime.Now:HH:mm:ss}";
});
}
}
catch (OperationCanceledException)
{
MyTextBox.Text = "Timer was cancelled.";
}
}
private void Window_Closed(object sender, EventArgs e)
{
// 窗口关闭时取消定时器
_cts.Cancel();
}
}
}
确保你的XAML文件中有一个名为MyTextBox的TextBox控件:
<Window x:Class="WpfAppWithPeriodicTimer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="PeriodicTimer Example" Height="200" Width="400"
Closed="Window_Closed">
<Grid>
<TextBox x:Name="MyTextBox" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16" IsReadOnly="True"/>
</Grid>
</Window>
Dispatcher.Invoke确保UI更新在主线程上进行。TimeSpan.FromSeconds(1)创建了一个周期为1秒的定时器。CancellationTokenSource控制定时器的生命周期。WaitForNextTickAsync方法异步等待下一个周期的到来。CancellationToken来停止定时器,而不需要显式调用停止方法。PeriodicTimer提供了简单的API接口,易于理解和使用。System.Timers.Timer,PeriodicTimer在资源管理和性能上更为高效。PeriodicTimer的精度取决于系统调度器,可能无法满足高精度需求。WaitForNextTickAsync方法是单线程的,如果任务执行时间超过间隔时间,可能导致任务堆积。