新增以防抖方式执行任务。

This commit is contained in:
FalconFly 2024-07-01 17:18:51 +08:00
parent 416b0cd37a
commit e62db70d44
2 changed files with 151 additions and 0 deletions

View File

@ -0,0 +1,42 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Falcon.SugarApi.Test
{
/// <summary>
/// 任务防抖测试
/// </summary>
[TestClass()]
public class ShakingTests
{
/// <summary>
/// 任务防抖测试
/// </summary>
[TestMethod()]
public void RunTest() {
var showMsg = () => Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")} show message!");
var reMsg = () => $"{DateTime.Now.ToString("HH:mm:ss")} show message!";
var task = new Task<string>(reMsg);
int span = 5;
var shaking = new Shaking(span);
//showMsg();
//await Task.Delay(5 * 1000);
//shaking.Run(showMsg);
Console.WriteLine($"以下方法调用3次应该有两个输出相隔{span}秒");
Console.WriteLine(reMsg());
shaking.Run(task);
task = new Task<string>(reMsg);
shaking.Run(task);
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")} {span}秒后记录第二个输出");
Console.WriteLine(task.Result);
Console.WriteLine("任务完成!");
}
}
}

109
Falcon.SugarApi/Shaking.cs Normal file
View File

@ -0,0 +1,109 @@
using System;
using System.Threading.Tasks;
namespace Falcon.SugarApi
{
/// <summary>
/// 防止抖动执行任务
/// <para>每个任务加入后都会等待一段时间后开始执行。如果在等待期间有新的任务加入,旧任务会被放弃并重新记录等待时间。</para>
/// <para>用这种方式可以防止同样的类似任务被频繁触发,
/// 比如用户连续快速点击按钮导致点击事件处理程序多次执行,用此类可以保证只执行一次。</para>
/// <para>但是也产生了一些副作用,第一是不管怎么样方法总是会等待一定时间后延迟触发。
/// 还有一个副作用,因为后加入的任务会导致先加入的未执行的任务被放弃,所以如果所有任务都必须执行,那就不要使用此类了。</para>
/// </summary>
public class Shaking:IDisposable
{
/// <summary>
/// 下一个要执行的任务
/// </summary>
protected Task? Next { get; set; }
/// <summary>
/// 执行计时器
/// </summary>
protected System.Timers.Timer Timer { get; set; }
/// <summary>
/// 等待执行时间
/// </summary>
public int TimespanSeconds { get; set; }
/// <summary>
/// 使用默认方式实例化
/// </summary>
public Shaking() : this(5) { }
/// <summary>
/// 实例化默认抖动执行间隔5秒
/// </summary>
/// <param name="timeSpanSeconds">抖动执行时间间隔。秒</param>
public Shaking(int timeSpanSeconds) {
this.TimespanSeconds = timeSpanSeconds * 1000;
this.Timer = new System.Timers.Timer {
Interval = this.TimespanSeconds
};
this.Timer.Elapsed += TimerTick;
this.Timer.Stop();
}
/// <summary>
/// 时间到达,执行任务
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void TimerTick(object? sender,EventArgs e) {
this.Timer.Stop();
this.Timer.Dispose();
if(this.Next == null) {
return;
}
var n = this.Next;
this.Next = null;
n.Start();
}
/// <summary>
/// 新增任务
/// <para>未执行任务将会放弃</para>
/// </summary>
/// <param name="task">要执行的任务</param>
public void Run(Task task) {
this.Next = task;
if(this.Timer != null) {
this.Timer.Stop();
this.Timer.Dispose();
}
this.Timer = new System.Timers.Timer {
Interval = this.TimespanSeconds,
};
this.Timer.Elapsed += TimerTick;
this.Timer.Start();
}
/// <summary>
/// 新增任务委托
/// <para>未执行任务将会放弃</para>
/// </summary>
/// <param name="action">要执行的委托</param>
public void Run(Action action) => Run(new Task(action));
/// <summary>
/// 释放资源,未执行的任务放弃
/// </summary>
public void Dispose() {
if(this.Timer != null) {
this.Timer.Stop();
this.Timer.Dispose();
}
this.Next = null;
GC.SuppressFinalize(this);
}
/// <summary>
/// 立即执行任务
/// </summary>
public void RunNow() {
var n = this.Next;
this.Next = null;
if(n == null) {
return;
}
if(this.Timer != null) {
this.Timer.Stop();
this.Timer.Dispose();
}
n.Start();
}
}
}