wcs_server_s7_baoying/Tools/CirculateTool/StartCirculation.cs

110 lines
3.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Reflection;
namespace CirculateTool;
/*
* 作者:菻蔃
* 版本时间2023年04月15日
*
* 注意配合特性使用
*
*/
/// <summary>
/// 定时任务类
/// </summary>
public class StartCirculation
{
/// <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>
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;
}
}
}
/// <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)
{
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;
}
}
}
/// <summary>
/// 开启一个方法
/// </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);
}
}
}
}