From e62db70d4416a1488cf9a8869c9ad403b1edaf66 Mon Sep 17 00:00:00 2001
From: FalconFly <12919280+falconfly@user.noreply.gitee.com>
Date: Mon, 1 Jul 2024 17:18:51 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BB=A5=E9=98=B2=E6=8A=96?=
=?UTF-8?q?=E6=96=B9=E5=BC=8F=E6=89=A7=E8=A1=8C=E4=BB=BB=E5=8A=A1=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Falcon.SugarApi.Test/ShakingTests.cs | 42 +++++++++++
Falcon.SugarApi/Shaking.cs | 109 +++++++++++++++++++++++++++
2 files changed, 151 insertions(+)
create mode 100644 Falcon.SugarApi.Test/ShakingTests.cs
create mode 100644 Falcon.SugarApi/Shaking.cs
diff --git a/Falcon.SugarApi.Test/ShakingTests.cs b/Falcon.SugarApi.Test/ShakingTests.cs
new file mode 100644
index 0000000..0c02375
--- /dev/null
+++ b/Falcon.SugarApi.Test/ShakingTests.cs
@@ -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
+{
+ ///
+ /// 任务防抖测试
+ ///
+ [TestClass()]
+ public class ShakingTests
+ {
+ ///
+ /// 任务防抖测试
+ ///
+ [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(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(reMsg);
+ shaking.Run(task);
+ Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss")} {span}秒后记录第二个输出");
+ Console.WriteLine(task.Result);
+ Console.WriteLine("任务完成!");
+ }
+ }
+}
diff --git a/Falcon.SugarApi/Shaking.cs b/Falcon.SugarApi/Shaking.cs
new file mode 100644
index 0000000..f3e17c0
--- /dev/null
+++ b/Falcon.SugarApi/Shaking.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Threading.Tasks;
+
+namespace Falcon.SugarApi
+{
+ ///
+ /// 防止抖动执行任务
+ /// 每个任务加入后都会等待一段时间后开始执行。如果在等待期间有新的任务加入,旧任务会被放弃并重新记录等待时间。
+ /// 用这种方式可以防止同样的类似任务被频繁触发,
+ /// 比如用户连续快速点击按钮导致点击事件处理程序多次执行,用此类可以保证只执行一次。
+ /// 但是也产生了一些副作用,第一是不管怎么样方法总是会等待一定时间后延迟触发。
+ /// 还有一个副作用,因为后加入的任务会导致先加入的未执行的任务被放弃,所以如果所有任务都必须执行,那就不要使用此类了。
+ ///
+ public class Shaking:IDisposable
+ {
+ ///
+ /// 下一个要执行的任务
+ ///
+ protected Task? Next { get; set; }
+ ///
+ /// 执行计时器
+ ///
+ protected System.Timers.Timer Timer { get; set; }
+ ///
+ /// 等待执行时间
+ ///
+ public int TimespanSeconds { get; set; }
+ ///
+ /// 使用默认方式实例化
+ ///
+ public Shaking() : this(5) { }
+ ///
+ /// 实例化,默认抖动执行间隔5秒
+ ///
+ /// 抖动执行时间间隔。秒
+ public Shaking(int timeSpanSeconds) {
+ this.TimespanSeconds = timeSpanSeconds * 1000;
+ this.Timer = new System.Timers.Timer {
+ Interval = this.TimespanSeconds
+ };
+ this.Timer.Elapsed += TimerTick;
+ this.Timer.Stop();
+ }
+ ///
+ /// 时间到达,执行任务
+ ///
+ ///
+ ///
+ 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();
+ }
+ ///
+ /// 新增任务
+ /// 未执行任务将会放弃
+ ///
+ /// 要执行的任务
+ 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();
+ }
+ ///
+ /// 新增任务委托
+ /// 未执行任务将会放弃
+ ///
+ /// 要执行的委托
+ public void Run(Action action) => Run(new Task(action));
+ ///
+ /// 释放资源,未执行的任务放弃
+ ///
+ public void Dispose() {
+ if(this.Timer != null) {
+ this.Timer.Stop();
+ this.Timer.Dispose();
+ }
+ this.Next = null;
+ GC.SuppressFinalize(this);
+ }
+ ///
+ /// 立即执行任务
+ ///
+ 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();
+ }
+ }
+}