using System.Reflection;
namespace CirculateTool;
/*
* 作者:菻蔃
* 版本时间:2023年04月15日
*
* 注意配合特性使用
*
*/
///
/// 定时任务类
///
public class StartCirculation
{
///
/// 触发的异常
///
public event ExceptionHandlerEvent? ExceptionHandler;
public delegate void ExceptionHandlerEvent(string methodDescription, Exception ex);
///
/// 显示相关信息
///
public event MessageHandlerEvent? MessageHandler;
public delegate void MessageHandlerEvent(string message);
///
/// 默认的循环时间
///
private readonly int _defaultCirculationTime = 500;
///
/// 启动一个程序集里面带有的类里面的定时方法
///
///
///
public virtual void StartAssemblyCirculation(Assembly assembly, object[]? instanceParams = null)
{
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;
}
}
}
///
/// 开启一个实例里面所有已经添加了特性的方法
///
///
///
public virtual void StartTask(Type type, object[]? instanceParams = null)
{
var methods = type.GetMethods();
foreach (var method in methods)
{
var attributes = method.GetCustomAttributes(false);
foreach (var attribute in attributes)
{
if (attribute is not CirculationAttribute needDurable) continue;
string methodDescription = needDurable.MethodDescription ?? $"{type.Name}.{method.Name}";
bool Action() => (bool)(method.Invoke(Activator.CreateInstance(type, instanceParams), []) ?? false);
StartTask(Action, methodDescription, needDurable.CirculationTime);
break;
}
}
}
///
/// 开启一个方法
///
///
///
///
///
public virtual async void StartTask(Func 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);
}
}
}
}