2024-05-14 16:30:56 +08:00
|
|
|
|
using System.Reflection;
|
2024-06-21 09:30:10 +08:00
|
|
|
|
using CirculateTool.Attribute;
|
|
|
|
|
|
using CirculateTool.Entity;
|
2024-05-14 16:30:56 +08:00
|
|
|
|
|
|
|
|
|
|
namespace CirculateTool;
|
|
|
|
|
|
/*
|
|
|
|
|
|
* 作者:菻蔃
|
|
|
|
|
|
* 版本时间:2023年04月15日
|
|
|
|
|
|
*
|
|
|
|
|
|
* 注意配合特性使用
|
|
|
|
|
|
*
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 定时任务类
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class StartCirculation
|
|
|
|
|
|
{
|
2024-06-21 09:30:10 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 指定时间执行的方法类
|
|
|
|
|
|
/// </summary>
|
2024-06-21 10:14:13 +08:00
|
|
|
|
protected static List<TimeTask> _timeTasks = [];
|
2024-05-14 16:30:56 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 触发的异常
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public event ExceptionHandlerEvent? ExceptionHandler;
|
|
|
|
|
|
|
|
|
|
|
|
public delegate void ExceptionHandlerEvent(string methodDescription, Exception ex);
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 显示相关信息
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public event MessageHandlerEvent? MessageHandler;
|
|
|
|
|
|
|
|
|
|
|
|
public delegate void MessageHandlerEvent(string message);
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 默认的循环时间
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private readonly int _defaultCirculationTime = 500;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 启动一个程序集里面带有<see cref="CirculationAttribute"/>的类里面的定时方法
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="assembly"></param>
|
|
|
|
|
|
/// <param name="instanceParams"></param>
|
2024-06-21 09:30:10 +08:00
|
|
|
|
public void StartAssemblyCirculation(Assembly assembly, object[]? instanceParams = null)
|
2024-05-14 16:30:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
Type[] types = assembly.GetTypes();
|
|
|
|
|
|
if (types.Length == 0) return;
|
|
|
|
|
|
foreach (Type type in types)
|
|
|
|
|
|
{
|
|
|
|
|
|
var attributes = type.GetCustomAttributes(false);
|
|
|
|
|
|
foreach (var attribute in attributes)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (attribute is not CirculationAttribute) continue;
|
|
|
|
|
|
StartTask(type, instanceParams);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 开启一个实例里面所有已经添加了特性<see cref="CirculationAttribute"/>的方法
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="type"></param>
|
|
|
|
|
|
/// <param name="instanceParams"></param>
|
|
|
|
|
|
public virtual void StartTask(Type type, object[]? instanceParams = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var methods = type.GetMethods();
|
|
|
|
|
|
foreach (var method in methods)
|
|
|
|
|
|
{
|
2024-06-21 09:30:10 +08:00
|
|
|
|
object[] attributes = method.GetCustomAttributes(false);
|
|
|
|
|
|
if(attributes.Length == 0) continue;
|
|
|
|
|
|
foreach (object attribute in attributes)
|
2024-05-14 16:30:56 +08:00
|
|
|
|
{
|
2024-06-21 09:30:10 +08:00
|
|
|
|
if(attribute == default) continue;
|
|
|
|
|
|
/* 定时执行的任务 */
|
|
|
|
|
|
if(attribute is CirculationAttribute needDurable)
|
|
|
|
|
|
{
|
|
|
|
|
|
string methodDescription = needDurable.MethodDescription ?? $"{type.Name}.{method.Name}";
|
|
|
|
|
|
bool Action() => (bool)(method.Invoke(Activator.CreateInstance(type, instanceParams), []) ?? false);
|
|
|
|
|
|
StartTask(Action, methodDescription, needDurable.CirculationTime);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* 每天指定时间执行 */
|
|
|
|
|
|
if (attribute is CirculationTimeAttribute timeCirculate)
|
|
|
|
|
|
{
|
|
|
|
|
|
string methodDescription = timeCirculate.MethodDescription ?? $"{type.Name}.{method.Name}";
|
|
|
|
|
|
MessageHandler?.Invoke($"定时器任务:{methodDescription},已经添加,执行时间为:{timeCirculate}");
|
|
|
|
|
|
foreach (var time in timeCirculate.Times)
|
|
|
|
|
|
{
|
|
|
|
|
|
_timeTasks.Add(new TimeTask
|
|
|
|
|
|
{
|
|
|
|
|
|
ExecuteTime = time,
|
|
|
|
|
|
Action = () => method.Invoke(Activator.CreateInstance(type, instanceParams), []),
|
|
|
|
|
|
Description = methodDescription,
|
|
|
|
|
|
IsRun = false
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/* END */
|
|
|
|
|
|
|
2024-05-14 16:30:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-21 09:30:10 +08:00
|
|
|
|
/* 执行按时执行的任务 ---- 方法内判断,若没有此类方法则不会执行 */
|
|
|
|
|
|
StartTimeTask();
|
2024-05-14 16:30:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-06-21 09:30:10 +08:00
|
|
|
|
/// 开启一个方法 ---- 隔一定时间执行一次
|
2024-05-14 16:30:56 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="action"></param>
|
|
|
|
|
|
/// <param name="description"></param>
|
|
|
|
|
|
/// <param name="durableTime"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public virtual async void StartTask(Func<bool> action, string? description = null, int? durableTime = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
int durableTimeValue = durableTime ?? _defaultCirculationTime;
|
|
|
|
|
|
string methodDescription = description ?? action.Method.Name;
|
|
|
|
|
|
CancellationTokenSource cts = new();
|
|
|
|
|
|
PeriodicTimer timer = new(new TimeSpan(0, 0, 0, 0, durableTimeValue));
|
|
|
|
|
|
MessageHandler?.Invoke($"定时器:{methodDescription},已经启动,执行间隔为:{durableTimeValue} 毫秒。");
|
|
|
|
|
|
while (await timer.WaitForNextTickAsync(cts.Token))
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var result = action();
|
|
|
|
|
|
if (result) continue;
|
|
|
|
|
|
await cts.CancelAsync();
|
|
|
|
|
|
MessageHandler?.Invoke($"定时器:{methodDescription},主动结束。");
|
|
|
|
|
|
return; // 该return会结束这个线程
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
ExceptionHandler?.Invoke(methodDescription, ex);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-21 09:30:10 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 执行按时间执行的任务
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public virtual async void StartTimeTask()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(_timeTasks.Count == 0) return;
|
|
|
|
|
|
CancellationTokenSource cts = new();
|
2024-06-21 10:14:13 +08:00
|
|
|
|
PeriodicTimer timer = new(new TimeSpan(0, 0, 0, 1, 0));
|
2024-06-21 09:30:10 +08:00
|
|
|
|
while (await timer.WaitForNextTickAsync(cts.Token))
|
|
|
|
|
|
{
|
|
|
|
|
|
string timeStr = DateTime.Now.ToString("HH:mm");
|
|
|
|
|
|
List<Task> taskList = [];
|
2024-06-21 10:14:13 +08:00
|
|
|
|
foreach (var task in _timeTasks)
|
2024-06-21 09:30:10 +08:00
|
|
|
|
{
|
2024-06-21 10:14:13 +08:00
|
|
|
|
taskList.Add(Task.Factory.StartNew(() =>
|
2024-06-21 09:30:10 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (task.ExecuteTime != timeStr)
|
|
|
|
|
|
{
|
|
|
|
|
|
task.IsRun = false; // 当时刻不匹配时,重置任务状态
|
2024-06-21 10:14:13 +08:00
|
|
|
|
return;
|
2024-06-21 09:30:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
if (task.ExecuteTime == timeStr && !task.IsRun) // 当时间匹配且任务未执行时,执行任务
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
2024-06-21 10:14:13 +08:00
|
|
|
|
task.Action!();
|
2024-06-21 09:30:10 +08:00
|
|
|
|
task.IsRun = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
ExceptionHandler?.Invoke(task.Description ?? task.Action!.Method.Name, ex);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-21 10:14:13 +08:00
|
|
|
|
}));
|
|
|
|
|
|
}
|
2024-06-21 09:30:10 +08:00
|
|
|
|
Task.WaitAll([.. taskList]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-14 16:30:56 +08:00
|
|
|
|
}
|