Timer定时器多线程执行任务的优化

  1. 在某个工控机项目上,需要定时、频繁从设备读到数据然后呈现在UI界面上,程序刚开始运行UI数据正常刷新,久了之后UI数据不变动内存使用也逐渐变大,不得已只能关闭软件重启,用户体验特别不好。

  1. 查阅了相关资料,Timer每隔固定的时间执行一次任务,不管上次任务有没有执行完,当任务消耗的时间大于定时器间隔的时间,任务就会累积并且消耗大量线程资源,因此有必要让线程有序、高效、安全地执行。

  1. 以下为调优后的代码,软件修改后再也没有内存飙升、UI数据不刷新的问题,希望能给大家提供参考

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        System.Timers.Timer timer = new System.Timers.Timer { AutoReset = true, Interval = 500 };
        Task task;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            timer.Elapsed += Timer_Elapsed;
            timer.Enabled = true;
        }

        private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            #region 当前任务未执行完成,下个任务不能启动,避免定时器中多线程重入问题
            if (task != null && task.IsCompleted == false)
            {
                return;
            }
            #endregion
            task?.Dispose();//任务执行完成后释放所拥有的资源
            lock (timer)
            {
                #region 启动新的任务,并等待任务完成
                task = Task.Run(() => DoSometion());
                task.Wait();
                #endregion
            }
        }

        public void DoSometion()
        {
            Thread.Sleep(5000);
            Console.WriteLine("执行DoSometion方法的当前线程ID:{0},时间:{1}", Thread.CurrentThread.ManagedThreadId, System.DateTime.Now.ToString("HH:mm:ss fff"));
        }

        private void button2_Click(object sender, EventArgs e)
        {
            timer.Stop();
        }
    }
}

你可能感兴趣的:(C#,c#,ui,开发语言,Timer)