You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
using System; using System.Collections.Generic; using System.Reflection; using System.Text; using System.Threading;
namespace Apewer {
/// <summary>Cron 特性,默认间隔为 60000 毫秒。</summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class CronAttribute : Attribute {
internal const int DefaultInterval = 60000;
private int _interval;
/// <summary>两次 Cron 执行的间隔毫秒数。</summary>
public int Interval { get { return _interval; } }
/// <summary>创建 Cron 特性,可指定两次 Cron 执行的间隔毫秒数。</summary>
public CronAttribute(int interval = DefaultInterval) { _interval = interval; }
#region Payload
// 传入。
Type _type = null; Logger _logger = null;
// 实时。
Thread _thread = null; bool _alive = false;
void Run() { _alive = true; _thread = new Thread(Payload); _thread.IsBackground = false; _thread.Start(); }
void Payload() { var moment = 500; var delay = 0; var sender = $"Cron-{_type.Name}"; while (true) { if (_break) break; if (delay <= 0) { delay = _interval; _logger.Text(sender, "Beginning"); try { var instance = Activator.CreateInstance(_type); RuntimeUtility.Dispose(instance); _logger.Text(sender, "Ended"); } catch (Exception ex) { _logger.Exception(sender, ex); } } else { Thread.Sleep(moment); delay = delay - moment; } } _alive = false; }
#endregion
#region CronInvoker
static object _start = new object(); static CronAttribute[] _crons = null; static bool _break = false;
static CronAttribute[] Init(IEnumerable<Assembly> assemblies = null, Logger logger = null) { var attributes = new List<CronAttribute>(); var added = new List<string>(); if (assemblies == null) assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) { var types = assembly.GetTypes(); foreach (var type in types) { var attribute = RuntimeUtility.GetAttribute<CronAttribute>(type); if (attribute == null) continue; if (added.Contains(type.FullName)) continue; if (!RuntimeUtility.CanNew(type)) continue; attribute._type = type; attribute._logger = logger; attributes.Add(attribute); } } return attributes.ToArray(); }
/// <summary>开始 Cron 调用(阻塞当前线程)。</summary>
/// <remarks>
/// 参数<br />
/// - assemblies: 包含 Cron 的程序集,不指定此参数时将在 AppDomain 中搜索;<br />
/// - logger: 日志记录程序,不指定此参数时将使用 Logger.Default。<br />
/// </remarks>
public static void Start(IEnumerable<Assembly> assemblies = null, Logger logger = null) { if (logger == null) logger = Logger.Default; lock (_start) { // 初始化。
_crons = Init(assemblies, logger); if (_crons.Length < 1) { logger.Error(nameof(CronAttribute), "没有找到带有 Cron 特性的类型。"); return; }
// 启动线程。
Console.CancelKeyPress += (s, e) => { _break = true; e.Cancel = true; }; logger.Text(nameof(CronAttribute), $"启动 {_crons.Length} 个 Cron 线程。"); foreach (var cron in _crons) cron.Run();
// 监视退出状态。
while (true) { Thread.Sleep(300); var alive = 0; for (var i = 0; i < _crons.Length; i++) if (_crons[i]._alive) alive += 1; if (alive < 1) break; } logger.Text(nameof(CronAttribute), "所有 Cron 已结束。"); } }
/// <summary>打断 Cron 循环,不打断正在执行的 Cron。</summary>
public static void Break() { _break = true; }
#endregion
}
}
|