13
6月
2020

WPF解决多次调用定时器事件导致的叠加问题

今天和大家分享一个WPF下定时器的使用技巧,可以有效规避多次调用定时器事件导致的叠加问题,让你将定时器运用的炉火纯青!

问题描述:

随着调用定时器事件次数的增加导致事件执行次数产生叠加,例如第1次打开定时器时事件执行1次,第2次打开定时器时事件执行2次…第N次打开定时器时事件执行N次。

原因分析:

在全局声明的定时器触发后,如不释放将会继续在程序中存在,当再次调用该定时器时系统会同时调用历史定时器和新的定时器事件导致叠加,但是如果释放了定时器,那么再次调用该定时器时将会找不到该对象,从而无法实现多次调用同一定时器事件。

解决方法:

将定时器的声明放到局部,即每次点击按钮或调用函数时重新声明一次定时器,重新声明定时器后系统将调用新的定时器事件,从而保证可以多次调用同一定时器事件。

实践演示:

新建一个WPF,添加两个Button,一个使用全局声明定时器,另一个使用局部声明定时器,点击按钮打开定时器调用事件,另外再添加一个TextBox用来显示信息,界面如图1所示:

interface

图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所示:

setp1

图2-第1次点击“定时器叠加测试”按钮结果

2)第2次点击“定时器叠加测试”按钮,文本显示2条信息,如图3所示:

setp2

图3-第2次点击“定时器叠加测试”按钮结果

3)第3次点击“定时器叠加测试”按钮,文本显示3条信息,如图4所示:

setp3

图4-第3次点击“定时器叠加测试”按钮结果

4)第1次点击“定时器优化测试”按钮,文本显示1条信息,如图5所示:

setp4

图5-第1次点击“定时器优化测试”按钮结果

5)第2次点击“定时器优化测试”按钮,文本显示1条信息,如图6所示:

setp5

图6-第2次点击“定时器优化测试”按钮结果

 

6)第3次点击“定时器优化测试”按钮,文本显示1条信息,如图7所示:

setp6

图7-第3次点击“定时器优化测试”按钮结果

技术总结:

1.在全局声明的定时器,多次调用时系统会同时触发历史定时器事件和新的定时器事件,从而导致叠加。

2.将定时器放到局部声明,每次调用时系统会将它当作一个新的定时器处理,这样就无所谓新旧事件,系统只执行当前的定时器事件。


原文链接:https://www.daboke.com/database/timerpractice.html

B站up主-编程自修室:https://space.bilibili.com/580719958

源码下载:timerSample

发表评论

邮箱地址不会被公开。

微信 OR 支付宝 扫描二维码
为本文作者 打个赏
pay_weixin pay_weixin
最喜欢你一言不合就打赏的样子了^_^