在某个工控机项目上,需要定时、频繁从设备读到数据然后呈现在UI界面上,程序刚开始运行UI数据正常刷新,久了之后UI数据不变动内存使用也逐渐变大,不得已只能关闭软件重启,用户体验特别不好。
查阅了相关资料,Timer每隔固定的时间执行一次任务,不管上次任务有没有执行完,当任务消耗的时间大于定时器间隔的时间,任务就会累积并且消耗大量线程资源,因此有必要让线程有序、高效、安全地执行。
以下为调优后的代码,软件修改后再也没有内存飙升、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();
}
}
}