今天和大家分享一个WPF下定时器的使用技巧,可以有效规避多次调用定时器事件导致的叠加问题,让你将定时器运用的炉火纯青!
问题描述:
随着调用定时器事件次数的增加导致事件执行次数产生叠加,例如第1次打开定时器时事件执行1次,第2次打开定时器时事件执行2次…第N次打开定时器时事件执行N次。
原因分析:
在全局声明的定时器触发后,如不释放将会继续在程序中存在,当再次调用该定时器时系统会同时调用历史定时器和新的定时器事件导致叠加,但是如果释放了定时器,那么再次调用该定时器时将会找不到该对象,从而无法实现多次调用同一定时器事件。
解决方法:
将定时器的声明放到局部,即每次点击按钮或调用函数时重新声明一次定时器,重新声明定时器后系统将调用新的定时器事件,从而保证可以多次调用同一定时器事件。
实践演示:
新建一个WPF,添加两个Button,一个使用全局声明定时器,另一个使用局部声明定时器,点击按钮打开定时器调用事件,另外再添加一个TextBox用来显示信息,界面如图1所示:
前端代码:
<Window x:Class="timerSample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:timerSample" mc:Ignorable="d" Title="WPF解决多次调用定时器事件导致的叠加问题" Height="450" Width="400"> <Grid Margin="0,0,3.6,-3"> <Button Content="定时器叠加测试" HorizontalAlignment="Left" VerticalAlignment="Top" Width="94" Margin="80,122,0,0" Height="26" Click="Button_Click"/> <Button Content="定时器优化测试" HorizontalAlignment="Left" VerticalAlignment="Top" Width="94" Margin="211,122,0,0" Height="26" Click="Button_Click_1" /> <TextBox x:Name="tbox1" HorizontalAlignment="Left" Height="118" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="225" Margin="80,175,0,0"/> </Grid> </Window>
后端代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Windows; using System.Windows.Threading; namespace timerSample { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } System.Timers.Timer timer1 = new System.Timers.Timer(1000);//全局声明,实例化Timer类,设置间隔时间为1000毫秒; private void Button_Click(object sender, RoutedEventArgs e) { tbox1.Clear(); timer1.Elapsed += new System.Timers.ElapsedEventHandler(funcTest1);//到达时间的时候执行事件; timer1.AutoReset = false;//设置是执行一次(false)还是一直执行(true); timer1.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件; timer1.Start();//启动 } private void Button_Click_1(object sender, RoutedEventArgs e) { tbox1.Clear(); System.Timers.Timer timer2 = new System.Timers.Timer(1000);//局部声明,实例化Timer类,设置间隔时间为1000毫秒; timer2.Elapsed += new System.Timers.ElapsedEventHandler(funcTest2);//到达时间的时候执行事件; timer2.AutoReset = false;//设置是执行一次(false)还是一直执行(true); timer2.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件; timer2.Start();//启动 } public void funcTest1(object source, System.Timers.ElapsedEventArgs e) { this.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate () { tbox1.Text += "测试时间:" + " " + "" + System.DateTime.Now.ToString("HH:mm:ss") + "" + "\r\n"; }); timer1.Stop();//停止 timer1.Enabled = false;//关闭 } public void funcTest2(object source, System.Timers.ElapsedEventArgs e) { this.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate () { tbox1.Text = "测试时间:" + " " + "" + System.DateTime.Now.ToString("HH:mm:ss") + ""; }); } } }
操作对比:
1)首次点击“定时器叠加测试”按钮,文本显示1条信息,如图2所示:
2)第2次点击“定时器叠加测试”按钮,文本显示2条信息,如图3所示:
3)第3次点击“定时器叠加测试”按钮,文本显示3条信息,如图4所示:
4)第1次点击“定时器优化测试”按钮,文本显示1条信息,如图5所示:
5)第2次点击“定时器优化测试”按钮,文本显示1条信息,如图6所示: